Skip to content

Legacy OLE2 .doc detected as XLS by filetype; no way to override the input format #4474

Description

@P1aster

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:

  1. 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.
  2. 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

  1. 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).
  2. DocumentConverter().convert("sample.doc")
  3. 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

Activity

  1. added a commit that references this issue on Oct 4, 2026
    58f1f8d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions