PaddlePaddle/PaddleOCR · error · ResponseFormatError
Batch response is missing extractResult.
Error message
Batch response is missing extractResult.
What it means
ResponseFormatError with 'Batch response is missing extractResult.' is thrown by getBatchStatus() when the batch status response's data object is not a record containing an extractResult array. The SDK's batch contract requires data.extractResult to be an array of per-job status objects; its absence means the response shape is not a valid batch status payload.
Source
Thrown at api_sdk/typescript/src/internal/poller.ts:69
if (status.state === "failed") {
throw new JobFailedError(jobId, status.errorMsg || "Unknown error");
}
await this.sleep(Math.min(interval, Math.max(0, deadline - Date.now())), signal);
interval = Math.min(interval * MULTIPLIER, MAX_INTERVAL);
}
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",View on GitHub (pinned to 2661c7c0ef)
Solutions
- Verify you are passing a batchId (returned at batch submission time), not a single jobId
- Capture the raw batch status response with a custom fetchImpl to see what data actually contains
- Align SDK and server versions — extractResult is part of the batch status contract
- Make test mocks return { data: { extractResult: [{ jobId, state, ... }] } }
Example fix
try {
const batch = await poller.getBatchStatus(batchId);
} catch (e) {
if (e instanceof ResponseFormatError && e.message.includes("extractResult")) {
logger.error("Not a valid batch response for", batchId);
}
} Defensive patterns
Strategy: validation
Validate before calling
const BATCH_ID_RE = /^batch-[\w-]+$/; // adjust to your server's format
function isPlausibleBatchId(id: string): boolean {
return BATCH_ID_RE.test(id);
} Type guard
function isBatchResponse(v: unknown): v is { extractResult: unknown[] } {
return typeof v === "object" && v !== null && Array.isArray((v as any).extractResult);
} Try / catch
try {
const batch = await poller.getBatchStatus(batchId);
} catch (e) {
if (e instanceof ResponseFormatError && e.message.includes("extractResult")) {
// not retryable as-is: verify batchId provenance and API version
throw new Error(`batchId '${batchId}' did not return a batch payload`);
}
throw e;
} Prevention
- Keep batchIds from submission separate from jobIds in your types to prevent mix-ups
- Contract-test batch endpoints after server upgrades
- Return the full extractResult array from test doubles
When it happens
Trigger: Calling getBatchStatus(batchId) where batchId is not a real batch (server returns an error-shaped or empty data object with 200), the endpoint version changed the field name, or a mock/stub omits extractResult.
Common situations: Passing a jobId instead of a batchId; batch retention expired server-side; SDK/server version drift renaming the field; test doubles returning simplified JSON.
Related errors
- Batch extractResult item is missing jobId.
- 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/1d8e1d1bbe929daf.
Report an issue: GitHub.