{"record":{"id":"6c052b4d6348e16f","repo":"PaddlePaddle/PaddleOCR","slug":"paddleocr-official-api-request-failed","errorCode":null,"errorMessage":"PaddleOCR official API request failed.","messagePattern":"PaddleOCR official API request failed\\.","errorType":"exception","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/internal/http.ts","lineNumber":170,"sourceCode":"    return resp.arrayBuffer();\n  }\n\n  private async fetchJson<T>(\n    url: string,\n    init: RequestInit,\n    signal?: AbortSignal,\n    withAuth: boolean = true,\n    timeoutMs?: number,\n  ): Promise<T> {\n    const resp = await this.fetch(url, init, signal, withAuth, timeoutMs);\n    let payload: APIResponse<T>;\n    try {\n      payload = await resp.json() as APIResponse<T>;\n    } catch (error) {\n      throw new ResponseFormatError(\"Expected a JSON response body.\", { cause: error });\n    }\n    if (payload.code !== undefined && payload.code !== 0) {\n      throw new APIError(resp.status, payload.msg || \"PaddleOCR official API request failed.\");\n    }\n    if (!payload || typeof payload !== \"object\" || !(\"data\" in payload)) {\n      throw new ResponseFormatError(\"Response body is missing data.\");\n    }\n    return payload.data;\n  }\n\n  private async fetch(\n    url: string,\n    init: RequestInit,\n    signal?: AbortSignal,\n    withAuth: boolean = true,\n    timeoutMs?: number,\n  ): Promise<Response> {\n    const headers: Record<string, string> = {\n      ...(init.headers as Record<string, string> || {}),\n    };\n    if (withAuth) {","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/internal/http.ts#L152-L188","documentation":"APIError with the fallback message 'PaddleOCR official API request failed.' is thrown from fetchJson<T>() when the parsed JSON body contains a non-zero business error `code` and the body supplies no `msg` field to use as the message instead. That is, the API returned HTTP 2xx but signaled failure in its JSON envelope (code !== 0) without explaining why. The HTTP status stored on the error (statusCode) will be whatever 2xx status the server sent.","triggerScenarios":"Calling any JSON endpoint (submit, status, batch status) where the backend envelope has code: 1 (or any non-zero) and omits msg — e.g. internal service errors, invalid parameter codes surfaced as envelope codes, or quota errors delivered with a 200 status.","commonSituations":"Backend version changes that add new business error codes; degraded service returning code!=0 with an empty message; race conditions where a job/batch ID is consumed twice; API contract drift between SDK version and server version.","solutions":["Upgrade the SDK to the latest version so newly introduced envelope codes are handled and surfaced with real messages","Log the full response by temporarily using a fetch wrapper (client accepts a custom fetchImpl) to capture the raw body and identify the business code","Retry with exponential backoff — envelope-only failures are frequently transient service-side states","If reproducible, report to PaddleOCR support with the endpoint, timestamp, and the raw code value"],"exampleFix":"try {\n  await client.submitJson(model, payload);\n} catch (e) {\n  if (e instanceof APIError && e.statusCode < 300) {\n    // envelope-level failure: code !== 0 with no msg\n    await backoffRetry(3, () => client.submitJson(model, payload));\n  }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isEnvelopeFailure(e: unknown): e is APIError {\n  return e instanceof APIError && e.statusCode >= 200 && e.statusCode < 300;\n}","tryCatchPattern":"try {\n  await client.submitJson(model, payload);\n} catch (e) {\n  if (e instanceof APIError && e.statusCode < 300) {\n    // envelope code !== 0 with no msg: transient backend state, back off and retry\n    await sleep(1000);\n    return client.submitJson(model, payload);\n  }\n  throw e;\n}","preventionTips":["Keep the SDK updated so server-side envelope changes are handled upstream","Instrument responses with a custom fetchImpl to capture unmapped business codes","Wrap submissions in an idempotent retry helper so transient envelope failures self-heal"],"tags":["api","envelope","http","typescript"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}