{"record":{"id":"41e59f0ffff60b0b","repo":"docling-project/docling","slug":"unexpected-type-self-path-or-stream","errorCode":null,"errorMessage":"Unexpected: {type(self.path_or_stream)=}","messagePattern":"Unexpected: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"docling/backend/json/docling_json_backend.py","lineNumber":48,"sourceCode":"    @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.JSON_DOCLING}\n\n    def _get_doc_or_err(self) -> Union[DoclingDocument, Exception]:\n        try:\n            json_data: Union[str, bytes]\n            if isinstance(self.path_or_stream, Path):\n                with open(self.path_or_stream, encoding=\"utf-8\") as f:\n                    json_data = f.read()\n            elif isinstance(self.path_or_stream, BytesIO):\n                json_data = self.path_or_stream.getvalue()\n            else:\n                raise RuntimeError(f\"Unexpected: {type(self.path_or_stream)=}\")\n            return DoclingDocument.model_validate_json(json_data=json_data)\n        except Exception as e:\n            return e\n\n    @override\n    def convert(self) -> DoclingDocument:\n        if isinstance(self._doc_or_err, DoclingDocument):\n            return self._doc_or_err\n        else:\n            raise self._doc_or_err\n","sourceCodeStart":30,"sourceCodeEnd":59,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/json/docling_json_backend.py#L30-L59","documentation":"DoclingJSONBackend._get_doc_or_err() only accepts Path (opened as UTF-8 text) or BytesIO inputs and raises RuntimeError for anything else; because the method captures exceptions and stores them, the RuntimeError is re-raised later from convert() rather than at construction. String paths and generic file objects are not part of the contract.","triggerScenarios":"Passing a str path, an open file object, or io.StringIO as path_or_stream to the JSON backend; the error then surfaces at convert() time, deferred from init.","commonSituations":"FastAPI/web handlers forwarding uploaded file objects; scripts using os.path strings; the deferred raise confusing developers because construction succeeded.","solutions":["Wrap inputs: Path(p) for strings, BytesIO(data) for raw bytes/streams","Check the exception at convert() time — init will not fail for a bad type","Ensure the payload is UTF-8 encoded JSON of a serialized DoclingDocument"],"exampleFix":"# before\nbackend = DoclingJSONBackend(in_doc, '/data/doc.docling.json')  # str: fails at convert()\n\n# after\nfrom pathlib import Path\nbackend = DoclingJSONBackend(in_doc, Path('/data/doc.docling.json'))","handlingStrategy":"type-guard","validationCode":"from io import BytesIO\nfrom pathlib import Path\n\nsrc = Path('/data/doc.docling.json') if isinstance(src, str) else src\nassert isinstance(src, (Path, BytesIO)), f'JSON backend needs Path or BytesIO, got {type(src)!r}'","typeGuard":"def is_json_backend_source(src) -> bool:\n    return isinstance(src, (Path, BytesIO))","tryCatchPattern":null,"preventionTips":["Normalize inputs to Path/BytesIO at the boundary","Remember this backend defers stored errors to convert(); validate types up front"],"tags":["json","type-error","api-contract","deferred-error"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}