PaddlePaddle/PaddleOCR · error · InvalidRequestError

resourceUrl is required.

Error message

resourceUrl is required.

What it means

Thrown by validate_result_json_url in paddleocr/_api_client/_core.py:186 when a completed (state 'done') job's data does not contain an object 'resultUrl'. For done jobs the SDK needs resultUrl.jsonUrl to download the JSONL results. A missing or non-object resultUrl means the server violated the documented done-job schema. It is a ResponseFormatError raised during result retrieval, not during submission.

Source

Thrown at api_sdk/typescript/src/client.ts:125

  async saveOcrResultResources(
    result: OCRResult,
    destination: string,
    options: SaveResourceOptions = {},
  ): Promise<string[]> {
    return this.saveResultResources(result, destination, options);
  }

  async saveDocumentParsingResultResources(
    result: DocParsingResult,
    destination: string,
    options: SaveResourceOptions = {},
  ): Promise<string[]> {
    return this.saveResultResources(result, destination, options);
  }

  private async saveResourceUrl(resourceUrl: string, destination: string, options: SaveResourceOptions): Promise<string> {
    if (!resourceUrl) {
      throw new InvalidRequestError("resourceUrl is required.");
    }
    let url: URL;
    try {
      url = new URL(resourceUrl);
    } catch (error) {
      throw new InvalidRequestError(`Invalid resource URL: ${resourceUrl}`, { cause: error });
    }
    const target = await this.resolveDestination(url, destination, options);
    const content = await this.http.fetchResource(resourceUrl);
    await writeFile(target, Buffer.from(content), { flag: options.overwrite ? "w" : "wx" });
    return target;
  }

  private async saveResultResources(
    result: OCRResult | DocParsingResult,
    destination: string,
    options: SaveResourceOptions,
  ): Promise<string[]> {

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Inspect the raw job status JSON (get_job_status output) to see the shape of data.resultUrl
  2. Retry the get_result call once — transient server-side serialization bugs can produce malformed done responses
  3. Upgrade the paddleocr SDK in case the resultUrl schema changed and the SDK was updated for it
  4. If the job's artifacts expired (old jobId), resubmit the document to create a fresh job
Defensive patterns

Strategy: try-catch

Validate before calling

status = client.get_job_status(job_id)
if status.get("state") == "done" and not isinstance(status.get("resultUrl"), dict):
    logger.warning("Job done but resultUrl missing; retrying status fetch")

Type guard

def has_result_url(data: dict) -> bool:
    return isinstance(data.get("resultUrl"), dict)

Try / catch

from paddleocr._api_client.errors import ResponseFormatError
try:
    result = client.get_result(job_id)
except ResponseFormatError as e:
    if "resultUrl" in str(e):
        time.sleep(5)  # artifact may still be settling
        result = client.get_result(job_id)

Prevention

When it happens

Trigger: Calling client.get_result() (or any path that validates a done job response) where the job status response's data lacks resultUrl or has it as a string/null instead of an object with jsonUrl.

Common situations: Server-side change to the result URL structure; a done job whose artifacts expired or were cleaned up; a partially-initialized job marked done without results; API version mismatch between SDK and server.

Related errors


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