CoreLoader opens every document with the no-preference overload:
https://github.com/opendocument-app/OpenDocument.droid/blob/main/app/src/main/java/app/opendocument/droid/background/CoreLoader.kt#L482
private fun open(path: String): DecodedFile = Odr.open(path)
In the core, open_file with no as_file_type builds its candidate list purely from list_file_types, which is magic::file_type(...). The file extension is never consulted, so when magic cannot place the file the candidate list is empty and it throws UnknownFileType — even for a format the core parses perfectly well.
odr-private/pdf/order-EK52VKL0.pdf is the case that showed this up. It is a genuine 8-page PDF that was saved with the HTTP response still attached, so %PDF-1.4 sits at byte 178 instead of byte 0:
HTTP/1.0 200 OK
Cache-Control: no-cache, private
Content-Disposition: inline
Content-Type: application/pdf
...
%PDF-1.4
Magic looks at offset 0 and finds nothing, so the app reports:
app.opendocument.core.OdrException$UnknownFileType: unknown file type
and the user gets "Unsupported file format. Try opening it in another app."
The core itself has no trouble with the file. Its reference output for it has all 8 pages and full metadata ("fileType": "pdf", "producer": "Skia/PDF m78"), because the test harness passes the type in rather than detecting it:
DecodePreference decode_preference;
decode_preference.as_file_type = test_file.type;
DecodedFile file = open(test_file.absolute_path, decode_preference, logger);
The app already knows the answer
MetadataLoader has determined a mime type by the time this runs, and it is sitting in FileLoader.Options.fileType — host() just never receives it. The core exposes both Odr.fileTypeByMimetype(String) and Odr.fileTypeByFileExtension(String), plus Odr.open(path, DecodePreference).
So passing what the app already established, as DecodePreference.asFileType or at least as fileTypePriority, would open this file and make detection more robust generally — content sniffing becomes the fallback rather than the only source of truth. Worth deciding whether the app's mime type should override magic outright or only be used when magic comes back empty.
Scope
One file out of 225 in a sweep of the whole corpus (#550), so the impact is narrow — but the failure mode is "the core can read your document and the app says it cannot", which is worth not having.
CoreLoaderopens every document with the no-preference overload:https://github.com/opendocument-app/OpenDocument.droid/blob/main/app/src/main/java/app/opendocument/droid/background/CoreLoader.kt#L482
In the core,
open_filewith noas_file_typebuilds its candidate list purely fromlist_file_types, which ismagic::file_type(...). The file extension is never consulted, so when magic cannot place the file the candidate list is empty and it throwsUnknownFileType— even for a format the core parses perfectly well.odr-private/pdf/order-EK52VKL0.pdfis the case that showed this up. It is a genuine 8-page PDF that was saved with the HTTP response still attached, so%PDF-1.4sits at byte 178 instead of byte 0:Magic looks at offset 0 and finds nothing, so the app reports:
and the user gets "Unsupported file format. Try opening it in another app."
The core itself has no trouble with the file. Its reference output for it has all 8 pages and full metadata (
"fileType": "pdf","producer": "Skia/PDF m78"), because the test harness passes the type in rather than detecting it:The app already knows the answer
MetadataLoaderhas determined a mime type by the time this runs, and it is sitting inFileLoader.Options.fileType—host()just never receives it. The core exposes bothOdr.fileTypeByMimetype(String)andOdr.fileTypeByFileExtension(String), plusOdr.open(path, DecodePreference).So passing what the app already established, as
DecodePreference.asFileTypeor at least asfileTypePriority, would open this file and make detection more robust generally — content sniffing becomes the fallback rather than the only source of truth. Worth deciding whether the app's mime type should override magic outright or only be used when magic comes back empty.Scope
One file out of 225 in a sweep of the whole corpus (#550), so the impact is narrow — but the failure mode is "the core can read your document and the app says it cannot", which is worth not having.