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

  1. Capture the raw submit response via a custom fetchImpl to see what field the server actually returned
  2. Align SDK and API versions — the jobId field name is part of the submit contract
  3. If you stub the API in tests, return { code: 0, msg: "ok", data: { jobId: "job-123" } }
  4. 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

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


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/b7ea3d2fb198b9ce. Report an issue: GitHub.