PaddlePaddle/PaddleOCR · error · ResponseFormatError

Status progress must be an object.

Error message

Status progress must be an object.

What it means

Thrown by normalizeProgress() when a job status response includes an extractProgress field whose value is neither absent/null nor a plain object. The poller tolerates missing progress entirely, but if progress data is present it must be an object with numeric totalPages/extractedPages fields. Any other JSON type (number, string, array, boolean) triggers this ResponseFormatError.

Source

Thrown at api_sdk/typescript/src/internal/poller.ts:133

  }
  if (!["pending", "running", "done", "failed"].includes(data.state)) {
    throw new ResponseFormatError(`Unknown job state: ${data.state}`);
  }
  return {
    jobId,
    state: data.state as JobStatus["state"],
    progress: normalizeProgress(data.extractProgress),
    resultUrl: isRecord(data.resultUrl) ? stringMap(data.resultUrl) : undefined,
    errorMsg: typeof data.errorMsg === "string" ? data.errorMsg : undefined,
  };
}

function normalizeProgress(progress: unknown): Progress | undefined {
  if (progress === undefined || progress === null) {
    return undefined;
  }
  if (!isRecord(progress)) {
    throw new ResponseFormatError("Status progress must be an object.");
  }
  return {
    totalPages: typeof progress.totalPages === "number" ? progress.totalPages : 0,
    extractedPages: typeof progress.extractedPages === "number" ? progress.extractedPages : 0,
    startTime: typeof progress.startTime === "string" ? progress.startTime : undefined,
    endTime: typeof progress.endTime === "string" ? progress.endTime : undefined,
  };
}

function resultJsonUrl(data: unknown): string {
  if (!isRecord(data) || !isRecord(data.resultUrl) || typeof data.resultUrl.jsonUrl !== "string") {
    throw new ResponseFormatError("Done job response is missing resultUrl.jsonUrl.");
  }
  return data.resultUrl.jsonUrl;
}

function stringMap(value: Record<string, unknown>): Record<string, string> {
  const result: Record<string, string> = {};

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Capture the raw status response and inspect the JSON type of extractProgress
  2. Fix the server to emit progress as an object { totalPages, extractedPages } or omit it entirely
  3. Upgrade/align SDK and server versions so both expect the object shape
  4. If the field is genuinely unused, remove it from the response

Example fix

// before (server response)
{ "state": "running", "extractProgress": 55 }

// after
{ "state": "running", "extractProgress": { "totalPages": 100, "extractedPages": 55 } }
Defensive patterns

Strategy: type-guard

Validate before calling

const raw = await client.getJobStatus(jobId);
if (raw.extractProgress != null && typeof raw.extractProgress !== "object") {
  // server emits non-object progress; strip it before handing the payload to the poller
  delete raw.extractProgress;
}

Type guard

function isProgressObject(v: unknown): v is { totalPages?: number; extractedPages?: number } {
  return v == null || (typeof v === "object" && !Array.isArray(v));
}

Try / catch

try { await poller.wait(jobId); } catch (e) {
  if (e instanceof ResponseFormatError && /progress must be an object/.test(e.message)) {
    // server-side serialization bug: report to API owner, fall back to non-progress polling
  } else throw e;
}

Prevention

When it happens

Trigger: Polling a job whose status response contains "extractProgress": 42, "extractProgress": "50%", or "extractProgress": [1,2] instead of an object like {"totalPages":10,"extractedPages":5}. Happens when the server changes progress serialization (e.g. flattening to a percentage number).

Common situations: Server refactor that switched progress from object to scalar percent; partial serialization bugs where progress is emitted as a JSON string; SDK version older than a server progress format change.

Related errors


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