docling-project/docling · error · DocumentLoadError

Could not initialize HTML backend for file with hash {self.d

Error message

Could not initialize HTML backend for file with hash {self.document_hash}.

What it means

HTMLDocumentBackend.__init__ wraps exceptions from reading the raw bytes and building the BeautifulSoup tree into DocumentLoadError. Because html.parser is extremely tolerant, the read step (OSError on a bad path, stream already consumed) is the most common cause; genuine parser errors also land here. The original exception is preserved as __cause__.

Source

Thrown at docling/backend/html_backend.py:479

        self._rendered_page_images: list[Image.Image] = []
        self._rendered_page_size: Optional[Size] = None
        self._suppressed_tag_ids_stack: list[set[str]] = []
        self._suppressed_tag_obj_ids_stack: list[set[int]] = []
        self._form_fields_by_key_id_stack: list[dict[str, _ExtractedFormField]] = []
        self._tag_name_by_docling_id_cache: dict[str, str] = {}
        self._generated_html_id_counter: int = 0
        self._render_visibility_cache: dict[int, bool] = {}

        try:
            raw = (
                path_or_stream.getvalue()
                if isinstance(path_or_stream, BytesIO)
                else Path(path_or_stream).read_bytes()
            )
            self._raw_html_bytes = raw
            self.soup = BeautifulSoup(raw, "html.parser")
        except Exception as e:
            raise DocumentLoadError(
                "Could not initialize HTML backend for file with "
                f"hash {self.document_hash}."
            ) from e

    @override
    def is_valid(self) -> bool:
        return self.soup is not None

    @classmethod
    @override
    def supports_pagination(cls) -> bool:
        return False

    @override
    def unload(self):
        if isinstance(self.path_or_stream, BytesIO):
            self.path_or_stream.close()
        self.path_or_stream = None

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Inspect exc.__cause__ to distinguish I/O errors from parser errors
  2. Verify Path.exists()/readable() or reset streams with seek(0) before conversion
  3. Read the bytes once yourself and pass a fresh BytesIO

Example fix

# before
res = converter.convert(html_path)

# after
raw = html_path.read_bytes()  # surfaces I/O problems directly
res = converter.convert(BytesIO(raw))
Defensive patterns

Strategy: try-catch

Validate before calling

src = Path(html_path)
assert src.is_file() and src.stat().st_size > 0, f'HTML source unreadable: {src}'
raw = src.read_bytes()  # surface I/O errors before the backend wraps them

Try / catch

try:
    result = converter.convert(BytesIO(raw))
except DocumentLoadError as exc:
    log.warning('HTML init failed: %s', exc.__cause__ or exc)
    raise

Prevention

When it happens

Trigger: Path that does not exist or lacks read permission; a BytesIO already drained by earlier code; rare tokenizer explosions on pathological inputs.

Common situations: Reusing a stream across two conversions; TOCTOU file deletion; chroot/container without read access to mounted HTML files.

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/5a38feed26263ca9. Report an issue: GitHub.