{"record":{"id":"0e0d0ac3f831be03","repo":"docling-project/docling","slug":"expected-an-opendocument-self-odf-type-r-but-go","errorCode":null,"errorMessage":"Expected an OpenDocument {self._odf_type!r} but got {self.odf_obj.get_type()!r}","messagePattern":"Expected an OpenDocument (.+?) but got (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"docling/backend/opendocument_backend.py","lineNumber":169,"sourceCode":"    _odf_type: str = \"\"  # \"text\", \"spreadsheet\" or \"presentation\"\n\n    @override\n    def __init__(\n        self,\n        in_doc: InputDocument,\n        path_or_stream: BytesIO | Path,\n        options: OdsBackendOptions | None = None,\n    ) -> None:\n        if not _ODFDO_AVAILABLE:\n            raise ImportError(_INSTALL_HINT) from _ODFDO_IMPORT_ERROR\n        super().__init__(in_doc, path_or_stream, options)\n        self.path_or_stream: BytesIO | Path = path_or_stream\n        self.valid: bool = False\n        self.odf_obj: OdfDocument = _load_odf_document(\n            path_or_stream, self.document_hash\n        )\n        if self._odf_type and self.odf_obj.get_type() != self._odf_type:\n            raise RuntimeError(\n                f\"Expected an OpenDocument {self._odf_type!r} but got \"\n                f\"{self.odf_obj.get_type()!r}\"\n            )\n        self.valid = True\n\n    @override\n    def is_valid(self) -> bool:\n        return self.valid\n\n    @override\n    def unload(self):\n        if isinstance(self.path_or_stream, BytesIO):\n            self.path_or_stream.close()\n        self.path_or_stream = None\n\n\ndef _find_true_data_bounds(table: OdfTable) -> tuple[int, int, int, int]:\n    \"\"\"Find the true data boundaries (min/max rows and columns) in an ODS table.","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/opendocument_backend.py#L151-L187","documentation":"RuntimeError raised in _OdfBaseBackend.__init__ after successfully loading an ODF package whose odfdo get_type() does not match the subclass's _odf_type ('text' for ODT, 'presentation' for ODP, 'spreadsheet' for ODS). It prevents, e.g., the ODT backend from walking a spreadsheet body.","triggerScenarios":"A .ods file renamed to .odt (or any ODF type/format mismatch) is dispatched to the wrong backend by extension-based format detection; the mimetype inside content.xml disagrees with the backend's expectation.","commonSituations":"User-uploaded files with wrong extensions, pipelines that guess InputFormat from the suffix instead of MIME sniffing, mixed ODF exports misnamed during bulk conversion.","solutions":["Detect the true type with odfdo or by reading the ODF mimetype entry and dispatch to the matching backend.","Fix the file extension to match the actual document type and retry.","Re-save the document from its native application with the correct type.","In custom pipelines, key InputFormat off python-magic/filetype detection rather than the filename suffix."],"exampleFix":"# before\nconv = DocumentConverter(format=[InputFormat.ODT])\nres = conv.convert('actually_a_sheet.odt')  # RuntimeError: expected 'text' got 'spreadsheet'\n\n# after\nimport filetype  # or read the ODF 'mimetype' entry\nkind = filetype.guess_mime(path)\nfmt = {'application/vnd.oasis.opendocument.spreadsheet': InputFormat.ODS,\n       'application/vnd.oasis.opendocument.text': InputFormat.ODT,\n       'application/vnd.oasis.opendocument.presentation': InputFormat.ODP}[kind]\nres = DocumentConverter(format=[fmt]).convert(path)","handlingStrategy":"validation","validationCode":"import zipfile\nwith zipfile.ZipFile(path) as z:\n    odf_type = z.read('mimetype').decode()\n# map mimetype -> InputFormat and dispatch accordingly","typeGuard":null,"tryCatchPattern":"try:\n    backend = OdsBackendClass(in_doc, path)\nexcept RuntimeError as e:\n    if 'Expected an OpenDocument' in str(e):\n        retry_with_correct_backend(detect_odf_type(path))","preventionTips":["Read the ODF 'mimetype' entry and route by it, not by file extension","Use content-based detection for user uploads","Keep a mimetype->InputFormat map next to your dispatcher"],"tags":["odf","format-mismatch","file-detection"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}