PaddlePaddle/PaddleOCR · error · InvalidRequestError
Invalid resource URL: ${resourceUrl}
Error message
Invalid resource URL: ${resourceUrl} What it means
Thrown by validate_result_json_url in paddleocr/_api_client/_core.py:189 when the done job's resultUrl object exists but its 'jsonUrl' field is not a non-empty string. jsonUrl is the pre-signed URL the SDK downloads JSONL results from; an empty/missing/null value makes download impossible. This is a ResponseFormatError indicating a malformed server response for a completed job.
Source
Thrown at api_sdk/typescript/src/client.ts:131
}
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[]> {
await this.requireExistingDirectory(destination);
const plans = this.collectResultResourcePlans(result);
const targets = plans.map((plan) => join(destination, plan.filename));
for (const target of targets) {
await this.requireWritableTarget(target, options);
}View on GitHub (pinned to 2661c7c0ef)
Solutions
- Wait a few seconds and poll job status again — jsonUrl may appear once artifact generation settles
- Dump the raw status response to confirm resultUrl contents
- If jsonUrl is consistently absent for done jobs, upgrade the SDK and/or report to PaddleOCR — the server response is malformed
- As a workaround, check whether resultUrl carries an alternative field (e.g. a zip URL) and fetch results manually
Defensive patterns
Strategy: try-catch
Validate before calling
status = client.get_job_status(job_id)
ru = status.get("resultUrl")
if isinstance(ru, dict) and not (isinstance(ru.get("jsonUrl"), str) and ru["jsonUrl"]:
print("jsonUrl not ready") Type guard
def has_json_url(data: dict) -> bool:
ru = data.get("resultUrl")
return isinstance(ru, dict) and isinstance(ru.get("jsonUrl"), str) and bool(ru["jsonUrl"]) Try / catch
from paddleocr._api_client.errors import ResponseFormatError
try:
result = client.get_result(job_id)
except ResponseFormatError as e:
if "jsonUrl" in str(e):
time.sleep(5)
result = client.get_result(job_id) Prevention
- Treat a just-flipped 'done' state as eventually consistent — retry result fetch once after a delay
- Monitor for schema drift on resultUrl in integration tests
When it happens
Trigger: Retrieving results of a done job where data.resultUrl exists but resultUrl.jsonUrl is absent, empty, null, or a non-string (e.g. a list of URLs).
Common situations: Result artifacts not yet generated when the job flipped to done; pre-signed URL generation failing server-side; schema drift in the API; truncated response from a proxy.
Related errors
- resourceUrl is required.
- Token is required. Set PADDLEOCR_ACCESS_TOKEN or pass token
- Model ${model} is not a document parsing model.
- File not found: ${path}
- Destination must be an existing directory: ${destination}
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/12acbc83095b26f5.
Report an issue: GitHub.