{"record":{"id":"92c10601e625df23","repo":"docling-project/docling","slug":"cannot-convert-box-note-with-hash-self-document-h","errorCode":null,"errorMessage":"Cannot convert Box Note with hash {self.document_hash}: no 'doc' node found.","messagePattern":"Cannot convert Box Note with hash (.+?): no 'doc' node found\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"docling/backend/boxnote_backend.py","lineNumber":91,"sourceCode":"\n    @override\n    def is_valid(self) -> bool:\n        return isinstance(self.data.get(\"doc\"), dict)\n\n    @classmethod\n    @override\n    def supports_pagination(cls) -> bool:\n        return False\n\n    @classmethod\n    @override\n    def supported_formats(cls) -> set[InputFormat]:\n        return {InputFormat.BOXNOTE}\n\n    @override\n    def convert(self) -> DoclingDocument:\n        if not self.is_valid():\n            raise RuntimeError(\n                f\"Cannot convert Box Note with hash {self.document_hash}: \"\n                \"no 'doc' node found.\"\n            )\n\n        origin = DocumentOrigin(\n            filename=self.file.name or \"file.boxnote\",\n            mimetype=\"application/vnd.box.boxnote\",\n            binary_hash=self.document_hash,\n        )\n        doc = DoclingDocument(name=self.file.stem or \"file\", origin=origin)\n\n        self._add_blocks(self.data[\"doc\"].get(\"content\", []), doc, None)\n        return doc\n\n    def _add_blocks(\n        self, nodes: list[dict], doc: DoclingDocument, parent: NodeItem | None\n    ) -> None:\n        for node in nodes:","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/boxnote_backend.py#L73-L109","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Call is_valid() (or let DocumentConverter do it) before convert(): if not backend.is_valid(): skip/report the file.","Pre-validate that the JSON root has a 'doc' object: isinstance(json.loads(raw).get('doc'), dict).","If the file came from an HTTP fetch, check the response status/body — you may have saved an API error payload as .boxnote.","Catch RuntimeError (and DocumentLoadError) per file in batch loops so one bad note does not kill the run."],"exampleFix":"# before\ndoc = BoxNoteDocumentBackend(inp, Path('note.boxnote')).convert()  # may raise\n\n# after\nbackend = BoxNoteDocumentBackend(inp, Path('note.boxnote'))\nif not backend.is_valid():\n    raise ValueError('not a current-format Box Note (no doc node)')\ndoc = backend.convert()","handlingStrategy":"validation","validationCode":"# Using the backend directly:\nbackend = BoxNoteDocumentBackend(inp, path)\nif not backend.is_valid():  # checks isinstance(data.get(\"doc\"), dict)\n    raise ValueError(f\"{path} has no 'doc' node; not a current Box Note\")\ndoc = backend.convert()","typeGuard":null,"tryCatchPattern":"try:\n    doc = backend.convert()\nexcept RuntimeError as e:\n    if \"no 'doc' node\" in str(e):\n        skip_and_report(path)\n    else:\n        raise","preventionTips":["Always gate convert() with is_valid() when using backends directly.","Prefer DocumentConverter, which enforces validity checks itself.","Validate that fetched Box API responses are actual note content, not error payloads."],"tags":["box-note","validation","convert"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}