PaddlePaddle/PaddleOCR · error · APIError

PaddleOCR official API request failed.

Error message

PaddleOCR official API request failed.

What it means

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.

Source

Thrown at api_sdk/typescript/src/internal/http.ts:170

    return resp.arrayBuffer();
  }

  private async fetchJson<T>(
    url: string,
    init: RequestInit,
    signal?: AbortSignal,
    withAuth: boolean = true,
    timeoutMs?: number,
  ): Promise<T> {
    const resp = await this.fetch(url, init, signal, withAuth, timeoutMs);
    let payload: APIResponse<T>;
    try {
      payload = await resp.json() as APIResponse<T>;
    } catch (error) {
      throw new ResponseFormatError("Expected a JSON response body.", { cause: error });
    }
    if (payload.code !== undefined && payload.code !== 0) {
      throw new APIError(resp.status, payload.msg || "PaddleOCR official API request failed.");
    }
    if (!payload || typeof payload !== "object" || !("data" in payload)) {
      throw new ResponseFormatError("Response body is missing data.");
    }
    return payload.data;
  }

  private async fetch(
    url: string,
    init: RequestInit,
    signal?: AbortSignal,
    withAuth: boolean = true,
    timeoutMs?: number,
  ): Promise<Response> {
    const headers: Record<string, string> = {
      ...(init.headers as Record<string, string> || {}),
    };
    if (withAuth) {

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Upgrade the SDK to the latest version so newly introduced envelope codes are handled and surfaced with real messages
  2. 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
  3. Retry with exponential backoff — envelope-only failures are frequently transient service-side states
  4. If reproducible, report to PaddleOCR support with the endpoint, timestamp, and the raw code value

Example fix

try {
  await client.submitJson(model, payload);
} catch (e) {
  if (e instanceof APIError && e.statusCode < 300) {
    // envelope-level failure: code !== 0 with no msg
    await backoffRetry(3, () => client.submitJson(model, payload));
  }
}
Defensive patterns

Strategy: retry

Type guard

function isEnvelopeFailure(e: unknown): e is APIError {
  return e instanceof APIError && e.statusCode >= 200 && e.statusCode < 300;
}

Try / catch

try {
  await client.submitJson(model, payload);
} catch (e) {
  if (e instanceof APIError && e.statusCode < 300) {
    // envelope code !== 0 with no msg: transient backend state, back off and retry
    await sleep(1000);
    return client.submitJson(model, payload);
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/6c052b4d6348e16f. Report an issue: GitHub.