PaddlePaddle/PaddleOCR · error · ResponseFormatError
Batch extractResult item is missing jobId.
Error message
Batch extractResult item is missing jobId.
What it means
ResponseFormatError with 'Batch extractResult item is missing jobId.' is thrown while mapping a batch status response when an element of data.extractResult is not an object with a string jobId. Every per-job entry in a batch must carry a jobId so the SDK can normalize it into a JobStatus; one malformed element fails the whole getBatchStatus() call.
Source
Thrown at api_sdk/typescript/src/internal/poller.ts:75
}
throw new PollTimeoutError(jobId, this.maxWaitTime);
}
async getStatus(jobId: string, signal?: AbortSignal): Promise<JobStatus> {
return normalizeStatus(jobId, await this.http.getJobStatus(jobId, signal));
}
async getBatchStatus(batchId: string, signal?: AbortSignal): Promise<BatchStatus> {
const data = await this.http.getBatchStatus(batchId, signal);
if (!isRecord(data) || !Array.isArray(data.extractResult)) {
throw new ResponseFormatError("Batch response is missing extractResult.");
}
return {
batchId,
jobs: data.extractResult.map((item) => {
if (!isRecord(item) || typeof item.jobId !== "string") {
throw new ResponseFormatError("Batch extractResult item is missing jobId.");
}
return normalizeStatus(item.jobId, item);
}),
};
}
private sleep(ms: number, signal?: AbortSignal): Promise<void> {
return new Promise((resolve, reject) => {
const timer = setTimeout(resolve, ms);
if (!signal) return;
signal.addEventListener(
"abort",
() => {
clearTimeout(timer);
reject(userAbortReason(signal));
},
{ once: true },
);View on GitHub (pinned to 2661c7c0ef)
Solutions
- Capture the raw extractResult via a custom fetchImpl and identify which element lacks jobId
- Upgrade the SDK / confirm server version — per-job field naming is part of the contract
- If the batch is permanently malformed, fall back to per-job getStatus() calls for jobIds you already know
- Fix test mocks to include jobId in every extractResult element
Example fix
try {
const batch = await poller.getBatchStatus(batchId);
} catch (e) {
if (e instanceof ResponseFormatError && e.message.includes("item is missing jobId")) {
// degraded mode: poll known jobs individually
const jobs = await Promise.all(knownJobIds.map(id => poller.getStatus(id)));
}
} Defensive patterns
Strategy: fallback
Validate before calling
function batchItemsAllHaveJobId(items: unknown[]): boolean {
return items.every((i) => typeof i === "object" && i !== null && typeof (i as any).jobId === "string");
} Type guard
function isBatchStatusPayload(v: unknown): v is { extractResult: Array<{ jobId: string }> } {
return typeof v === "object" && v !== null
&& Array.isArray((v as any).extractResult)
&& (v as any).extractResult.every(
(i: unknown) => typeof i === "object" && i !== null && typeof (i as { jobId?: unknown }).jobId === "string"
);
} Try / catch
try {
batch = await poller.getBatchStatus(batchId);
} catch (e) {
if (e instanceof ResponseFormatError && e.message.includes("item is missing jobId")) {
// fallback: degrade to per-job polling with ids you already hold
batch = { batchId, jobs: await Promise.all(knownJobIds.map(id => poller.getStatus(id))) };
} else throw e;
} Prevention
- Persist per-job ids from submission so batch status is a convenience, not a dependency
- Include jobId in every extractResult element of mocks
- Capture raw batch payloads when the contract breaks to identify the malformed element
When it happens
Trigger: getBatchStatus(batchId) where the server's extractResult array contains null entries, entries keyed differently (id/job_id), or inline error objects for jobs that failed before assignment — a single bad element aborts mapping of the entire batch.
Common situations: Backend version drift renaming per-job fields; server emitting placeholder entries for rejected submissions; partially-implemented mocks in tests; corrupt batch state after an incident.
Related errors
- Batch response is missing extractResult.
- Response body is missing data.
- Submit response is missing jobId.
- Status response is missing state.
- File not found: ${path}
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/9fc7cb4bd3176e3f.
Report an issue: GitHub.