{"record":{"id":"e7ebf215c278cafc","repo":"PaddlePaddle/PaddleOCR","slug":"malformed-ocr-result-payload-e","errorCode":null,"errorMessage":"Malformed OCR result payload: {e}","messagePattern":"Malformed OCR result payload: (.+?)","errorType":"exception","errorClass":"ResultParseError","httpStatus":null,"severity":"error","filePath":"paddleocr/_api_client/_poller.py","lineNumber":121,"sourceCode":"            if isinstance(result.get(\"dataInfo\"), dict):\n                data_info.update(result[\"dataInfo\"])\n            for item in result[\"ocrResults\"]:\n                pages.append(\n                    OCRPage(\n                        pruned_result=item[\"prunedResult\"],\n                        ocr_image_url=item.get(\"ocrImage\"),\n                        doc_preprocessing_image_url=item.get(\"docPreprocessingImage\"),\n                        input_image_url=item.get(\"inputImage\"),\n                        raw=item,\n                    )\n                )\n        return OCRResult(\n            job_id=job_id,\n            pages=pages,\n            data_info=data_info,\n        )\n    except (KeyError, TypeError) as e:\n        raise ResultParseError(f\"Malformed OCR result payload: {e}\") from e\n\n\ndef parse_doc_parsing_result(job_id: str, jsonl_data: list) -> DocParsingResult:\n    try:\n        pages = []\n        data_info = {}\n        for line_obj in jsonl_data:\n            result = line_obj[\"result\"]\n            if isinstance(result.get(\"dataInfo\"), dict):\n                data_info.update(result[\"dataInfo\"])\n            for item in result[\"layoutParsingResults\"]:\n                markdown = item[\"markdown\"]\n                pages.append(\n                    DocParsingPage(\n                        markdown_text=markdown[\"text\"],\n                        markdown_images=markdown.get(\"images\", {}),\n                        output_images=item.get(\"outputImages\", {}),\n                        pruned_result=item.get(\"prunedResult\"),","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr/_api_client/_poller.py#L103-L139","documentation":"ResultParseError raised while converting the downloaded JSONL into an OCRResult: a KeyError or TypeError occurred accessing the expected structure (each line's 'result' dict, 'layoutParsingResults' list, per-page keys, prunedResult, etc.). The chained exception names the exact missing key or bad type.","triggerScenarios":"parse_ocr_result(job_id, jsonl_data) runs on the fetched JSONL after a 'done' job; it raises when 'result' is missing from a line, 'layoutParsingResults' is absent or not iterable, or a page entry is not a dict / lacks required keys. Typically caused by a server whose result schema differs from what this client version expects.","commonSituations":"Client library version newer/older than the PaddleOCR server (schema drift, e.g. renamed keys); a doc-parsing (PP-StructureV3) result fed into the OCR parser because the wrong job type/API was called; partial result file where one line has a different shape (e.g. an error-notification line).","solutions":["Inspect the raw JSONL (it is available on the exception path — dump it before parsing) and compare keys against what parse_ocr_result expects","Align client and server versions so the result schema matches","If you submitted via a document-parsing endpoint, use the document-parsing flow / parse_doc_parsing_result instead of the OCR flow","Report/patch the parser if the server legitimately renamed a key, and pin the working version until then"],"exampleFix":"# before\nresult = client.ocr(job_id)  # ResultParseError: KeyError('layoutParsingResults')\n\n# after\nraw_lines = client._http.fetch_jsonl(json_url)\nprint(raw_lines)  # inspect actual schema first\nresult = parse_ocr_result(job_id, raw_lines)  # then parse with corrected expectations","handlingStrategy":"try-catch","validationCode":"def looks_like_ocr_result(jsonl_data) -> bool:\n    return bool(jsonl_data) and all(\n        isinstance(l, dict) and 'result' in l and 'layoutParsingResults' in l['result']\n        for l in jsonl_data\n    )","typeGuard":"def is_ocr_payload(obj: object) -> bool:\n    if not isinstance(obj, list) or not obj:\n        return False\n    first = obj[0]\n    return isinstance(first, dict) and isinstance(first.get('result'), dict) \\n        and isinstance(first['result'].get('layoutParsingResults'), list)","tryCatchPattern":"try:\n    result = parse_ocr_result(job_id, jsonl_data)\nexcept ResultParseError as e:\n    logger.error(\"schema mismatch for job %s: %s; raw=%s\", job_id, e, jsonl_data)\n    raise","preventionTips":["Snapshot raw JSONL for every job while developing so schema surprises are debuggable","Version-lock client to server; test the parse path after any server upgrade","Route document-parsing jobs through the doc-parsing API, not the OCR one"],"tags":["parsing","schema-mismatch","ocr"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}