PaddlePaddle/PaddleOCR · error · ResponseFormatError
Unknown job state: ${data.state}
Error message
Unknown job state: ${data.state} What it means
Thrown by normalizeStatus() while polling a job: the status response carried a state field, but its value is not one of the four states this SDK understands ("pending", "running", "done", "failed"). It is a ResponseFormatError, meaning the server reply violated the contract the SDK's poller was built against. This almost always indicates the server and SDK disagree about the job-state enum.
Source
Thrown at api_sdk/typescript/src/internal/poller.ts:117
throw new PollTimeoutError(jobId, this.maxWaitTime);
}
try {
return await operation();
} catch (error) {
if (error instanceof RequestTimeoutError && error.timeoutMs === remainingMs) {
throw new PollTimeoutError(jobId, this.maxWaitTime, { cause: error });
}
throw error;
}
}
}
function normalizeStatus(jobId: string, data: unknown): JobStatus {
if (!isRecord(data) || typeof data.state !== "string") {
throw new ResponseFormatError("Status response is missing state.");
}
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 {View on GitHub (pinned to 2661c7c0ef)
Solutions
- Log the raw HTTP status response body to see the exact state string the server sent
- Upgrade the TypeScript SDK to a version that knows the new state value (check changelog for job state additions)
- If you control the server, restrict emitted states to pending/running/done/failed until clients are updated
- If the new state is terminal-cancel, add server-side mapping to an SDK-known state or expose it via errorMsg on state="failed"
Example fix
// before
const result = await client.waitForResult(jobId); // throws on unknown state
// after
const job = await client.getJob(jobId); // raw status call that tolerates unknown states
if (["pending","running"].includes(job.state)) { /* keep polling via waitForResult */ }
else if (job.state === "done") { /* fetch result */ }
else { /* handle terminal/unknown without the strict poller */ } Defensive patterns
Strategy: type-guard
Validate before calling
const KNOWN_STATES = new Set(["pending", "running", "done", "failed"]);
const status = await client.getJobStatus(jobId); // raw status call
if (!KNOWN_STATES.has(status.state)) {
console.warn(`Server reported unknown state ${status.state}; SDK poller would throw`);
} Type guard
function isKnownJobState(s: string): s is "pending" | "running" | "done" | "failed" {
return ["pending", "running", "done", "failed"].includes(s);
} Try / catch
try {
const result = await poller.wait(jobId);
} catch (e) {
if (e instanceof ResponseFormatError && /Unknown job state/.test(e.message)) {
// version skew with server: fetch raw status and decide manually
} else throw e;
} Prevention
- Pin SDK and server to compatible API versions; check the changelog when the server adds job states
- Monitor raw status payloads in staging so new state values surface before they break the poller
- Never invent state strings in mock servers; use the four documented states
When it happens
Trigger: Calling the poll/wait API (e.g. waitForResult or whatever drives normalizeStatus) against a server that returns a newer state such as "cancelled", "canceling", "expired", "queued", or a typo'd value like "Done". Also produced by mock/stub servers that invent state names.
Common situations: Server API upgraded to add a cancel/timeout state while the client pins an older SDK; test harness returning hardcoded JSON with a wrong state string; regional deployments with divergent API versions.
Related errors
- Status progress must be an object.
- Done job response is missing resultUrl.jsonUrl.
- Job ${jobId} failed: ${errorMsg}
- Timed out after ${timeoutMs}ms waiting for job ${jobId}
- Document parsing result item is missing result.layoutParsing
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/4d31bed3f195a573.
Report an issue: GitHub.