{"record":{"id":"b998db642da4d626","repo":"PaddlePaddle/PaddleOCR","slug":"http-statuscode-text","errorCode":null,"errorMessage":"HTTP ${statusCode}: ${text}","messagePattern":"HTTP (.+?): (.+?)","errorType":"exception","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/internal/http.ts","lineNumber":245,"sourceCode":"    if (resp.ok) return resp;\n\n    let text = await resp.text();\n    try {\n      const payload = JSON.parse(text) as { msg?: string; message?: string; errorMsg?: string };\n      text = payload.msg || payload.message || payload.errorMsg || text;\n    } catch {\n      // Keep raw response text.\n    }\n    if (resp.status === 401 || resp.status === 403) {\n      throw new AuthError(`Authentication failed: ${text}`);\n    } else if (resp.status === 400) {\n      throw new InvalidRequestError(`Bad request: ${text}`);\n    } else if (resp.status === 429) {\n      throw new RateLimitError(`Rate limit exceeded: ${text}`);\n    } else if (resp.status === 503 || resp.status === 504) {\n      throw new ServiceUnavailableError(resp.status, `Service unavailable: ${text}`);\n    } else {\n      throw new APIError(resp.status, text);\n    }\n  }\n}\n\nfunction requireJobId(data: SubmitResponse): string {\n  if (!data || typeof data.jobId !== \"string\" || data.jobId.length === 0) {\n    throw new ResponseFormatError(\"Submit response is missing jobId.\");\n  }\n  return data.jobId;\n}\n","sourceCodeStart":227,"sourceCodeEnd":256,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/internal/http.ts#L227-L256","documentation":"APIError with 'HTTP <status>: <text>' is the fallback for any non-2xx status not mapped to a specific class (401/403, 400, 429, 503/504 have their own errors). The statusCode property carries the numeric status and the message embeds the best explanation found in the body. Common triggers include 404 (wrong jobId or endpoint), 405, 408, 413 (payload too large), and 500.","triggerScenarios":"Polling or fetching results for a jobId that does not exist or expired server-side (404); uploading a body larger than the gateway limit (413); unexpected server crashes (500); calling an endpoint removed or renamed in a newer API version (404/405).","commonSituations":"Persisting jobIds in a database and resuming days later after server-side retention expired; oversized PDFs exceeding upload limits; SDK version older than a breaking API change; transient 500s during incidents.","solutions":["Branch on e.statusCode: 404 → the jobId/URL is gone (stop retrying, submit a new job); 413 → compress or split the file; 5xx → retry with backoff","Read the embedded body text — it usually names the real problem even for unmapped statuses","For 404s on old jobIds, design your pipeline to consume results promptly or re-submit","Upgrade the SDK if the endpoint shape changed server-side"],"exampleFix":"try {\n  const result = await poller.waitForResult(jobId);\n} catch (e) {\n  if (e instanceof APIError) {\n    if (e.statusCode === 404) return resubmitJob(jobId);       // expired/unknown job\n    if (e.statusCode === 413) throw new Error(\"File too large\");\n    if (e.statusCode >= 500) await backoffRetry(() => poller.waitForResult(jobId));\n  }\n}","handlingStrategy":"try-catch","validationCode":"function isRetryableStatus(code: number): boolean {\n  return code === 408 || code === 429 || code >= 500;\n}","typeGuard":"function isAPIErrorWithStatus(e: unknown): e is APIError & { statusCode: number } {\n  return e instanceof APIError && typeof e.statusCode === \"number\";\n}","tryCatchPattern":"try {\n  const result = await poller.waitForResult(jobId);\n} catch (e) {\n  if (e instanceof APIError) {\n    if (e.statusCode === 404) return resubmit();            // job gone: permanent\n    if (e.statusCode === 413) throw new Error(\"File too large\");\n    if (e.statusCode >= 500 || e.statusCode === 408) return backoffRetry();\n  }\n  throw e;\n}","preventionTips":["Branch on e.statusCode: 4xx (except 408/429) is permanent, 5xx/408 is retryable","Consume results promptly; do not rely on jobIds surviving long retention windows","Compress or split uploads to stay under gateway body limits"],"tags":["http","status-code","api","typescript"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}