{"record":{"id":"b1f506b561f9ab75","repo":"PaddlePaddle/PaddleOCR","slug":"response-body-must-be-a-json-object","errorCode":null,"errorMessage":"Response body must be a JSON object.","messagePattern":"Response body must be a JSON object\\.","errorType":"exception","errorClass":"ResponseFormatError","httpStatus":null,"severity":"error","filePath":"paddleocr/_api_client/_core.py","lineNumber":164,"sourceCode":"\n\ndef raise_for_status(status_code: int, msg: str) -> None:\n    if 200 <= status_code < 300:\n        return\n    if status_code in (401, 403):\n        raise AuthError(f\"Authentication failed: {msg}\")\n    if status_code == 400:\n        raise InvalidRequestError(f\"Bad request: {msg}\")\n    if status_code == 429:\n        raise RateLimitError(f\"Rate limit exceeded: {msg}\")\n    if status_code in (503, 504):\n        raise ServiceUnavailableError(status_code, f\"Service unavailable: {msg}\")\n    raise APIError(status_code, msg)\n\n\ndef unwrap_api_response(payload: dict, status_code: int) -> dict:\n    if not isinstance(payload, dict):\n        raise ResponseFormatError(\"Response body must be a JSON object.\")\n    code = payload.get(\"code\", 0)\n    if code not in (0, None):\n        raise APIError(status_code, extract_api_message_from_payload(payload) or \"\")\n    data = payload.get(\"data\")\n    if not isinstance(data, dict):\n        raise ResponseFormatError(\"Response JSON must contain object field 'data'.\")\n    return data\n\n\ndef extract_job_id(data: dict) -> str:\n    job_id = data.get(\"jobId\")\n    if not isinstance(job_id, str) or not job_id:\n        raise ResponseFormatError(\n            \"Response data must contain non-empty string 'jobId'.\"\n        )\n    return job_id\n\n","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr/_api_client/_core.py#L146-L182","documentation":"Raised as ResponseFormatError by unwrap_api_response() when the parsed response body is not a JSON object (dict). The client expects an envelope object with 'code'/'data'; receiving a list, string, number, or null means the response is not the expected API shape.","triggerScenarios":"Any API call whose body parses to non-dict JSON: an array response, a bare string, or a proxy returning a JSON scalar. Also triggered by double-encoded or wrongly-decoded bodies.","commonSituations":"API version drift changing the envelope, gateways rewriting responses, or test mocks returning list payloads instead of the {code, data} envelope.","solutions":["Log the raw response text and content-type to identify what was actually returned.","Confirm the base URL points at the real API endpoint, not a docs page or proxy error.","Update the paddleocr package to match the service schema version.","Fix mocks to return the documented {code, data} envelope."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from paddleocr._api_client.errors import ResponseFormatError\ntry:\n    data = await client._http.get_job_status(job_id)\nexcept ResponseFormatError as e:\n    log.error(\"non-object JSON body: %s\", e)\n    raise","preventionTips":["Point the client at the official base URL; avoid rewriting proxies in front of it.","Keep test doubles aligned with the {code, data} envelope."],"tags":["response-format","json","parsing","api"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}