docling-project/docling · error · RuntimeError

Cannot convert Box Note with hash {self.document_hash}: no '

Error message

Cannot convert Box Note with hash {self.document_hash}: no 'doc' node found.

What it means

BoxNoteDocumentBackend.convert() raises this RuntimeError when convert() is called on a backend whose is_valid() is False, i.e. the loaded JSON has no top-level 'doc' dict. Unlike the load-time errors, this one fires at conversion time and only if you bypass the usual validity gate. The DocumentConverter pipeline normally checks validity before converting, so hitting it usually means direct backend usage or an empty/malformed payload that slipped through.

Source

Thrown at docling/backend/boxnote_backend.py:91

    @override
    def is_valid(self) -> bool:
        return isinstance(self.data.get("doc"), dict)

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

    @classmethod
    @override
    def supported_formats(cls) -> set[InputFormat]:
        return {InputFormat.BOXNOTE}

    @override
    def convert(self) -> DoclingDocument:
        if not self.is_valid():
            raise RuntimeError(
                f"Cannot convert Box Note with hash {self.document_hash}: "
                "no 'doc' node found."
            )

        origin = DocumentOrigin(
            filename=self.file.name or "file.boxnote",
            mimetype="application/vnd.box.boxnote",
            binary_hash=self.document_hash,
        )
        doc = DoclingDocument(name=self.file.stem or "file", origin=origin)

        self._add_blocks(self.data["doc"].get("content", []), doc, None)
        return doc

    def _add_blocks(
        self, nodes: list[dict], doc: DoclingDocument, parent: NodeItem | None
    ) -> None:
        for node in nodes:

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Call is_valid() (or let DocumentConverter do it) before convert(): if not backend.is_valid(): skip/report the file.
  2. Pre-validate that the JSON root has a 'doc' object: isinstance(json.loads(raw).get('doc'), dict).
  3. If the file came from an HTTP fetch, check the response status/body — you may have saved an API error payload as .boxnote.
  4. Catch RuntimeError (and DocumentLoadError) per file in batch loops so one bad note does not kill the run.

Example fix

# before
doc = BoxNoteDocumentBackend(inp, Path('note.boxnote')).convert()  # may raise

# after
backend = BoxNoteDocumentBackend(inp, Path('note.boxnote'))
if not backend.is_valid():
    raise ValueError('not a current-format Box Note (no doc node)')
doc = backend.convert()
Defensive patterns

Strategy: validation

Validate before calling

# Using the backend directly:
backend = BoxNoteDocumentBackend(inp, path)
if not backend.is_valid():  # checks isinstance(data.get("doc"), dict)
    raise ValueError(f"{path} has no 'doc' node; not a current Box Note")
doc = backend.convert()

Try / catch

try:
    doc = backend.convert()
except RuntimeError as e:
    if "no 'doc' node" in str(e):
        skip_and_report(path)
    else:
        raise

Prevention

When it happens

Trigger: Calling backend.convert() directly without checking backend.is_valid(); or a pipeline path that converts a .boxnote whose JSON is valid but lacks a 'doc' key (e.g. an empty object, a JSON array, or an unrelated JSON file renamed .boxnote).

Common situations: Custom pipelines that instantiate BoxNoteDocumentBackend directly; batch jobs that route any *.boxnote file to this backend without content validation; Box API responses that returned an error JSON body instead of note content.

Related errors


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