Bug
A legacy Word .doc (OLE2) is routed to the Excel backend and fails to convert:
detected formats: [<InputFormat.XLS: 'xls'>]
An unexpected error occurred while opening the document source.doc
Input document source.doc is not valid.
_DocumentConversionInput._guess_format takes the MIME from filetype.guess_mime() and only falls back to the extension when filetype returns nothing. For this file filetype returns application/vnd.ms-excel, so the .doc extension is never consulted and MsWordDocumentBackend (which would convert it via LibreOffice) is never used.
The cause is in filetype's Xls matcher. It accepts any OLE2 file whose first sector after the header starts with FD FF FF FF and has 0x00/0x02 at offset 518. That is a FAT sector marker, not anything Excel-specific, so any OLE2 container laid out with a FAT sector first matches as Excel. The Doc matcher only recognises a Word 97+ FIB in sector 0 (EC A5 C1 00) or a Word.Document.8 CompObj string, so it never gets a chance. We hit this on Word 6.0 documents (1990s archives) that contain a WordDocument stream:
$ file sample.doc
Composite Document File V2 Document, ... Name of Creating Application: Microsoft Word 6.0 ...
>>> b = open("sample.doc", "rb").read(1024); b[512:520].hex(" "), b[518]
('fd ff ff ff 08 00 00 00', 0)
>>> filetype.guess_mime("sample.doc")
'application/vnd.ms-excel'
>>> puremagic.magic_file("sample.doc")[0].mime_type
'application/msword'
Docling's own .doc path works for these files once it reaches the Word backend, so the only problem is detection. We can't share the original files, but any OLE2 .doc with the layout above reproduces it.
Two possible fixes, either would solve it:
- Let callers state the format. For example an optional
input_format on convert() / convert_all() (or on DocumentStream), used instead of _guess_format when set. Pipelines that already identify files upstream could then pass their answer through. Today the only workarounds are patching _guess_format or pre-converting the file.
- Don't trust
filetype for OLE2 containers. When the bytes are OLE2 (D0 CF 11 E0 A1 B1 1A E1), resolve doc/xls/ppt from the stream names in the directory (WordDocument, Workbook/Book, PowerPoint Document), or at least prefer the extension when it is one of those three. Another option is moving detection to puremagic, which identifies these files correctly. filetype has not had a release since 1.2.0 (Nov 2022), so a fix there seems unlikely.
Steps to reproduce
- Take an OLE2 Word 6.0
.doc whose first sector after the header is a FAT sector (bytes 512..515 are FD FF FF FF, byte 518 is 0x00).
DocumentConverter().convert("sample.doc")
- The log shows
detected formats: [XLS] and the conversion fails with Input document ... is not valid.
Docling version
2.130.0. The detection logic is unchanged on main / 2.132.0.
Python version
Python 3.13
Bug
A legacy Word
.doc(OLE2) is routed to the Excel backend and fails to convert:_DocumentConversionInput._guess_formattakes the MIME fromfiletype.guess_mime()and only falls back to the extension whenfiletypereturns nothing. For this filefiletypereturnsapplication/vnd.ms-excel, so the.docextension is never consulted andMsWordDocumentBackend(which would convert it via LibreOffice) is never used.The cause is in
filetype'sXlsmatcher. It accepts any OLE2 file whose first sector after the header starts withFD FF FF FFand has0x00/0x02at offset 518. That is a FAT sector marker, not anything Excel-specific, so any OLE2 container laid out with a FAT sector first matches as Excel. TheDocmatcher only recognises a Word 97+ FIB in sector 0 (EC A5 C1 00) or aWord.Document.8CompObj string, so it never gets a chance. We hit this on Word 6.0 documents (1990s archives) that contain aWordDocumentstream:Docling's own
.docpath works for these files once it reaches the Word backend, so the only problem is detection. We can't share the original files, but any OLE2.docwith the layout above reproduces it.Two possible fixes, either would solve it:
input_formatonconvert()/convert_all()(or onDocumentStream), used instead of_guess_formatwhen set. Pipelines that already identify files upstream could then pass their answer through. Today the only workarounds are patching_guess_formator pre-converting the file.filetypefor OLE2 containers. When the bytes are OLE2 (D0 CF 11 E0 A1 B1 1A E1), resolvedoc/xls/pptfrom the stream names in the directory (WordDocument,Workbook/Book,PowerPoint Document), or at least prefer the extension when it is one of those three. Another option is moving detection topuremagic, which identifies these files correctly.filetypehas not had a release since 1.2.0 (Nov 2022), so a fix there seems unlikely.Steps to reproduce
.docwhose first sector after the header is a FAT sector (bytes 512..515 areFD FF FF FF, byte 518 is0x00).DocumentConverter().convert("sample.doc")detected formats: [XLS]and the conversion fails withInput document ... is not valid.Docling version
2.130.0. The detection logic is unchanged on
main/ 2.132.0.Python version
Python 3.13