PaddlePaddle/PaddleOCR · error · ResponseFormatError
Submit response is missing jobId.
Error message
Submit response is missing jobId.
What it means
ResponseFormatError with 'Submit response is missing jobId.' comes from the requireJobId() guard: the submit call succeeded (HTTP 2xx, envelope code 0, data present) but data.jobId is not a non-empty string. The SDK requires every successful submission to return a usable jobId because all downstream operations (status polling, result fetch) key off it.
Source
Thrown at api_sdk/typescript/src/internal/http.ts:252
// Keep raw response text.
}
if (resp.status === 401 || resp.status === 403) {
throw new AuthError(`Authentication failed: ${text}`);
} else if (resp.status === 400) {
throw new InvalidRequestError(`Bad request: ${text}`);
} else if (resp.status === 429) {
throw new RateLimitError(`Rate limit exceeded: ${text}`);
} else if (resp.status === 503 || resp.status === 504) {
throw new ServiceUnavailableError(resp.status, `Service unavailable: ${text}`);
} else {
throw new APIError(resp.status, text);
}
}
}
function requireJobId(data: SubmitResponse): string {
if (!data || typeof data.jobId !== "string" || data.jobId.length === 0) {
throw new ResponseFormatError("Submit response is missing jobId.");
}
return data.jobId;
}
View on GitHub (pinned to 2661c7c0ef)
Solutions
- Capture the raw submit response via a custom fetchImpl to see what field the server actually returned
- Align SDK and API versions — the jobId field name is part of the submit contract
- If you stub the API in tests, return { code: 0, msg: "ok", data: { jobId: "job-123" } }
- Retry once: a transient serialization bug can occasionally emit an empty jobId
Example fix
try {
const jobId = await client.submitJson(model, payload);
} catch (e) {
if (e instanceof ResponseFormatError && e.message.includes("jobId")) {
// contract violation: log raw traffic and re-submit
logger.error("Submit contract broken", e);
return client.submitJson(model, payload);
}
throw e;
} Defensive patterns
Strategy: type-guard
Validate before calling
function hasJobId(data: unknown): data is { jobId: string } {
return typeof data === "object" && data !== null
&& typeof (data as any).jobId === "string" && (data as any).jobId.length > 0;
} Type guard
function isSubmitResponse(v: unknown): v is { jobId: string } {
return typeof v === "object" && v !== null && typeof (v as { jobId?: unknown }).jobId === "string";
} Try / catch
try {
jobId = await client.submitJson(model, payload);
} catch (e) {
if (e instanceof ResponseFormatError && e.message.includes("jobId")) {
// contract violation, retrying may help once; otherwise capture raw traffic
jobId = await client.submitJson(model, payload);
} else throw e;
} Prevention
- Make mocks return { code: 0, msg: "ok", data: { jobId: "job-1" } }
- Smoke-test submit → poll → result against staging after any API upgrade
- Keep SDK and server versions aligned; the jobId field name is contractual
When it happens
Trigger: submitJson() or submitFile() where the server's data object returns an empty jobId, a numeric/null jobId, or a renamed field (e.g. id or job_id after an API version change) — typically after backend contract drift or when pointing at a mock/stub server.
Common situations: Mock servers in tests returning { data: {} }; server-side A/B changes to field naming; SDK version out of sync with the deployed API; middleware stripping response fields.
Related errors
- Response body is missing data.
- Batch response is missing extractResult.
- Batch extractResult item is missing jobId.
- Status response is missing state.
- Expected a JSON response body.
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/b7ea3d2fb198b9ce.
Report an issue: GitHub.