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.

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.

Appendix: 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)