docling-project/docling · error · DocumentLoadError
MsExcelDocumentBackend could not load document with hash {se
Error message
MsExcelDocumentBackend could not load document with hash {self.document_hash} What it means
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.
Source
Thrown at docling/backend/msexcel_backend.py:343
"ignore",
message=r"The image .* will be removed because it cannot be read",
category=UserWarning,
module=r"openpyxl\.reader\.drawings",
)
if isinstance(self.path_or_stream, BytesIO):
self.workbook = load_workbook(
filename=self.path_or_stream, data_only=True
)
elif isinstance(self.path_or_stream, Path):
self.workbook = load_workbook(
filename=str(self.path_or_stream), data_only=True
)
self.valid = self.workbook is not None
except Exception as e:
self.valid = False
raise DocumentLoadError(
f"MsExcelDocumentBackend could not load document with hash {self.document_hash}"
) from e
def _parse_threaded_comments(
self, sheet_name: str
) -> dict[str, tuple[str, str, datetime | None]]:
"""Parse threaded comments from Excel XML for a specific sheet.
Returns a dict mapping cell coordinates to (author, text, timestamp) tuples.
Only works when path_or_stream is a Path (not BytesIO).
Security Note:
Uses secure XML parser configuration to prevent XXE attacks and validates
ZIP file paths to prevent zip-slip attacks.
"""
threaded_comments: dict[str, tuple[str, str, datetime | None]] = {}
# Only extract from Path objects (BytesIO is consumed by load_workbook)View on GitHub (pinned to 61d76f1ff3)
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.
Example fix
# before
result = converter.convert('report.xlsx') # actually a CSV renamed
# after
import filetype
kind = filetype.guess('report.xlsx')
if kind is None or 'sheet' not in (kind.mime or ''):
raise ValueError('not a real xlsx; route to CSV/legacy backend')
result = converter.convert('report.xlsx') Defensive patterns
Strategy: try-catch
Validate before calling
import filetype
def is_real_xlsx(path: str) -> bool:
kind = filetype.guess(path)
return kind is not None and kind.mime == (
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
) Try / catch
from docling.core.exceptions import DocumentLoadError
try:
result = converter.convert(xlsx_path)
except DocumentLoadError as e:
log.error('workbook load failed (%s): %s', xlsx_path, e.__cause__)
quarantine(xlsx_path) Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- docling-parse could not load document {self.document_hash}:
- MsPowerpointDocumentBackend could not load document with has
- CsvDocumentBackend could not load document with hash {self.d
- docling-parse could not load document {self.document_hash}.
- Could not initialize the EBCDIC backend for file with hash {
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/445a972278ba97dd.
Report an issue: GitHub.