{"record":{"id":"445a972278ba97dd","repo":"docling-project/docling","slug":"msexceldocumentbackend-could-not-load-document-wit","errorCode":null,"errorMessage":"MsExcelDocumentBackend could not load document with hash {self.document_hash}","messagePattern":"MsExcelDocumentBackend could not load document with hash (.+?)","errorType":"exception","errorClass":"DocumentLoadError","httpStatus":null,"severity":"error","filePath":"docling/backend/msexcel_backend.py","lineNumber":343,"sourceCode":"                    \"ignore\",\n                    message=r\"The image .* will be removed because it cannot be read\",\n                    category=UserWarning,\n                    module=r\"openpyxl\\.reader\\.drawings\",\n                )\n                if isinstance(self.path_or_stream, BytesIO):\n                    self.workbook = load_workbook(\n                        filename=self.path_or_stream, data_only=True\n                    )\n                elif isinstance(self.path_or_stream, Path):\n                    self.workbook = load_workbook(\n                        filename=str(self.path_or_stream), data_only=True\n                    )\n\n            self.valid = self.workbook is not None\n        except Exception as e:\n            self.valid = False\n\n            raise DocumentLoadError(\n                f\"MsExcelDocumentBackend could not load document with hash {self.document_hash}\"\n            ) from e\n\n    def _parse_threaded_comments(\n        self, sheet_name: str\n    ) -> dict[str, tuple[str, str, datetime | None]]:\n        \"\"\"Parse threaded comments from Excel XML for a specific sheet.\n\n        Returns a dict mapping cell coordinates to (author, text, timestamp) tuples.\n        Only works when path_or_stream is a Path (not BytesIO).\n\n        Security Note:\n            Uses secure XML parser configuration to prevent XXE attacks and validates\n            ZIP file paths to prevent zip-slip attacks.\n        \"\"\"\n        threaded_comments: dict[str, tuple[str, str, datetime | None]] = {}\n\n        # Only extract from Path objects (BytesIO is consumed by load_workbook)","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/msexcel_backend.py#L325-L361","documentation":"DocumentLoadError raised by MsExcelDocumentBackend when openpyxl's load_workbook() throws while opening the workbook (any exception during init is caught, valid is set False, and the error is re-raised wrapped). The chained __cause__ holds the real openpyxl failure: bad zip container, corrupt workbook.xml, unsupported/legacy format, password-protected file, etc.","triggerScenarios":"Calling convert() on a file that is not a valid OOXML workbook despite the .xlsx extension: an .xls renamed to .xlsx, an Excel 2003 XML spreadsheet, a CSV with .xlsx suffix, an encrypted workbook, or a file produced by a tool writing non-standard xlsx. Legacy .xls input that failed LibreOffice-based conversion to xlsx also lands here.","commonSituations":"User uploads with mislabeled extensions, password-protected workbooks, files generated by old ERP exports, truncated uploads, or missing LibreOffice when feeding true .xls files (the xls→xlsx pre-conversion fails).","solutions":["Inspect e.__cause__ on the DocumentLoadError to see openpyxl's underlying reason.","Open the file in Excel/LibreOffice and re-save as .xlsx to normalize the format.","For real .xls input, ensure soffice/LibreOffice is installed and on PATH so convert_to_modern_format works.","Detect mislabeled files up front (python-magic / filetype) and route CSV/legacy formats to the proper backend."],"exampleFix":"# before\nresult = converter.convert('report.xlsx')  # actually a CSV renamed\n\n# after\nimport filetype\nkind = filetype.guess('report.xlsx')\nif kind is None or 'sheet' not in (kind.mime or ''):\n    raise ValueError('not a real xlsx; route to CSV/legacy backend')\nresult = converter.convert('report.xlsx')","handlingStrategy":"try-catch","validationCode":"import filetype\n\ndef is_real_xlsx(path: str) -> bool:\n    kind = filetype.guess(path)\n    return kind is not None and kind.mime == (\n        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\n    )","typeGuard":null,"tryCatchPattern":"from docling.core.exceptions import DocumentLoadError\ntry:\n    result = converter.convert(xlsx_path)\nexcept DocumentLoadError as e:\n    log.error('workbook load failed (%s): %s', xlsx_path, e.__cause__)\n    quarantine(xlsx_path)","preventionTips":["Sniff true file type at upload; reject mislabeled extensions.","Decrypt password-protected workbooks before conversion.","For legacy .xls, verify soffice is installed and on PATH."],"tags":["excel","document-load","openpyxl","corrupt-file"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}