{"record":{"id":"01e65a73cf6aee4f","repo":"PaddlePaddle/PaddleOCR","slug":"response-body-is-not-valid-json-e","errorCode":null,"errorMessage":"Response body is not valid JSON: {e}","messagePattern":"Response body is not valid JSON: (.+?)","errorType":"exception","errorClass":"ResponseFormatError","httpStatus":null,"severity":"error","filePath":"paddleocr/_api_client/_async_http.py","lineNumber":187,"sourceCode":"            return\n        try:\n            body = await resp.json()\n            msg = (\n                extract_api_message_from_payload(body)\n                if isinstance(body, dict)\n                else None\n            )\n            if not msg:\n                msg = await resp.text()\n        except Exception:\n            msg = await resp.text()\n        raise_for_status(resp.status, msg)\n\n    async def _response_data(self, resp) -> Dict[str, Any]:\n        try:\n            payload = await resp.json()\n        except Exception as e:\n            raise ResponseFormatError(f\"Response body is not valid JSON: {e}\") from e\n        return unwrap_api_response(payload, resp.status)\n","sourceCodeStart":169,"sourceCodeEnd":189,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr/_api_client/_async_http.py#L169-L189","documentation":"ResponseFormatError from _response_data in the async API client: after an HTTP 2xx, the body must parse as JSON (await resp.json()); any parse failure raises with the underlying exception chained. The client assumes successful responses are JSON API envelopes and unwraps them via unwrap_api_response.","triggerScenarios":"Server returns 200 with HTML (login page, maintenance page), plain-text acknowledgment, or an empty body; a proxy or gateway rewriting the response; wrong content-type from a misrouted endpoint.","commonSituations":"API base URL pointing at a web UI instead of the API host; captive portals in CI networks; partial responses from interrupted connections.","solutions":["Check the base_url/host configuration points at the actual API endpoint, not a frontend.","Reproduce with curl and inspect the raw body and Content-Type of the failing response.","Retry once — transient gateway HTML pages are common.","Report/upgrade if the service legitimately returns a non-JSON success body in a newer version."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import aiohttp, asyncio\n\nasync def endpoint_returns_json(base_url: str) -> bool:\n    try:\n        async with aiohttp.ClientSession() as s:\n            async with s.get(base_url) as r:\n                ct = r.headers.get(\"Content-Type\", \"\")\n                return \"json\" in ct\n    except aiohttp.ClientError:\n        return False","typeGuard":null,"tryCatchPattern":"from paddleocr._api_client.errors import ResponseFormatError\n\ntry:\n    result = await client.parse_document(...)\nexcept ResponseFormatError as e:\n    # 2xx with non-JSON body: usually wrong host or gateway page; do NOT retry blindly\n    log.error(\"endpoint returned non-JSON success body: %s\", e)\n    raise","preventionTips":["Point base_url at the API host, not the web UI host.","Add a health/echo request at client construction to fail fast on misrouted endpoints.","Treat ResponseFormatError as configuration smell — retry only after verifying the raw body."],"tags":["python","asyncio","json","api-client","http"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}