{"record":{"id":"bc54161377581ec1","repo":"PaddlePaddle/PaddleOCR","slug":"http-status-code-message","errorCode":null,"errorMessage":"HTTP {status_code}: {message}","messagePattern":"HTTP (.+?): (.+?)","errorType":"exception","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"paddleocr/_api_client/_core.py","lineNumber":167,"sourceCode":"    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\ndef validate_result_json_url(data: dict) -> str:\n    result_url = data.get(\"resultUrl\")\n    if not isinstance(result_url, dict):","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr/_api_client/_core.py#L149-L185","documentation":"Raised as APIError by unwrap_api_response() when the response envelope's 'code' field is a non-zero error code (or non-None), or by raise_for_status() for any non-2xx status not mapped to a more specific error (e.g. 404, 500). The message is 'HTTP {status_code}: {message}' or the payload-extracted msg/errorMsg/message. It is the generic catch-all for service-reported failures.","triggerScenarios":"Envelope-level error codes from the service (code != 0 with a 200 status), or HTTP statuses like 404 (wrong endpoint/job id), 405, or 500 that fall through the specific handlers.","commonSituations":"Querying a deleted or nonexistent job id (404), server bugs (500), wrong base URL path, or business-rule errors returned inside the envelope code field.","solutions":["Inspect the status code and embedded message to classify the failure.","For 404, verify the job/resource id and the endpoint path.","For 500 or envelope codes, retry once with backoff; if it repeats, report with the request id.","Ensure you are on the current package version so envelope handling matches the service."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from paddleocr._api_client.errors import APIError, PaddleOCRAPIError\ntry:\n    result = await client.ocr(file_path=p)\nexcept AuthError:\n    raise\nexcept InvalidRequestError:\n    raise\nexcept APIError as e:  # generic bucket (404/500/envelope codes)\n    if e.status_code and e.status_code >= 500:\n        await asyncio.sleep(2)  # one retry for server faults\n        result = await client.ocr(file_path=p)\n    else:\n        raise","preventionTips":["Catch specific subclasses first; use APIError only as the last bucket.","Persist request ids / job ids so 404/500 reports are actionable.","Treat 4xx APIError as permanent and 5xx as retryable."],"tags":["http","api","catch-all","server-side"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}