PaddlePaddle/PaddleOCR · error · ResponseFormatError
Done job response is missing resultUrl.jsonUrl.
Error message
Done job response is missing resultUrl.jsonUrl.
What it means
Thrown by resultJsonUrl() when a job reaches the "done" state but its response does not contain a resultUrl object with a string jsonUrl. The poller treats a done job as incomplete without a result location, so it refuses rather than returning a result it cannot fetch. This is a ResponseFormatError pointing at a server-side contract violation or an incomplete job payload.
Source
Thrown at api_sdk/typescript/src/internal/poller.ts:145
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> = {};
for (const [key, val] of Object.entries(value)) {
if (typeof val === "string") {
result[key] = val;
}
}
return result;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
View on GitHub (pinned to 2661c7c0ef)
Solutions
- Log the full done-state response body to see what resultUrl actually contains
- If resultUrl is a plain string, the server is on an older API shape — align SDK and server versions
- If the field is intermittently missing, fix the server to publish the result URL atomically with the done transition
- As a caller, retry the status fetch once after a short delay if you control the server and suspect the publish race
Example fix
// before (server response)
{ "state": "done", "resultUrl": "https://cdn/.../result.json" }
// after
{ "state": "done", "resultUrl": { "jsonUrl": "https://cdn/.../result.json" } } Defensive patterns
Strategy: validation
Validate before calling
const job = await client.getJob(jobId);
if (job.state === "done" && !(typeof job.resultUrl?.jsonUrl === "string")) {
// done without a result location: retry once after a delay, then report server bug
} Type guard
function hasJsonUrl(job: unknown): job is { resultUrl: { jsonUrl: string } } {
const j = job as Record<string, any>;
return typeof j?.resultUrl?.jsonUrl === "string";
} Try / catch
try { await poller.wait(jobId); } catch (e) {
if (e instanceof ResponseFormatError && /resultUrl\.jsonUrl/.test(e.message)) {
// likely a publish race on the server: re-fetch status once after ~1s before giving up
} else throw e;
} Prevention
- On the server, write the result URL before flipping state to done (atomic completion)
- Add integration tests asserting the done payload always contains resultUrl.jsonUrl
- Log the full done response when this fires to distinguish rename vs race
When it happens
Trigger: Poller observes state="done" and immediately tries to read data.resultUrl.jsonUrl, but the server returned done without resultUrl, with resultUrl as a string URL instead of an object, or with jsonUrl missing/non-string. Also occurs when jobs are marked done before the result artifact URL is written.
Common situations: Race on the server between status flip to done and result upload; server renames resultUrl.jsonUrl (e.g. to resultUrl.json); resultUrl serialized as a plain string in an older API version.
Related errors
- Unknown job state: ${data.state}
- Status progress must be an object.
- 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/1f3fc237ed25824a.
Report an issue: GitHub.