PaddlePaddle/PaddleOCR · warning · InvalidRequestError

Unsafe resource filename: ${key}

Error message

Unsafe resource filename: ${key}

What it means

Raised as NetworkError from fetch_jsonl in paddleocr/_api_client/_http.py:192 when the connection to the pre-signed resultUrl fails (DNS, TLS, reset, refused). The result file lives on object storage, a different host from the API — so this can fail even when API connectivity is fine (e.g. storage domain blocked). The job succeeded; only the artifact download failed and can be retried while the pre-signed URL is valid.

Source

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

  for (const [key, val] of Object.entries(value)) {
    if (typeof val === "string") {
      result[key] = val;
    }
  }
  return result;
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null;
}

function isDocParsingResult(result: OCRResult | DocParsingResult): result is DocParsingResult {
  return result.pages.some((page) => "markdownText" in page);
}

function safeMapKeyFilename(key: string): string {
  if (!key || key === "." || key === ".." || key.includes("/") || key.includes("\\") || key.startsWith(".")) {
    throw new InvalidRequestError(`Unsafe resource filename: ${key}`);
  }
  return key;
}

function safeUrlBasename(url: URL): string {
  const name = basename(url.pathname) || "resource";
  if (name === "." || name === "..") {
    return "resource";
  }
  return name;
}

function resourceExtension(resourceUrl: string): string {
  try {
    const url = new URL(resourceUrl);
    return extname(url.pathname);
  } catch {
    return "";

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Extract jsonUrl from job status and test it directly (curl) from the same environment
  2. Whitelist the object-storage/CDN host in firewall/proxy rules
  3. Retry promptly — pre-signed URLs expire; if expired, re-fetch job status for a fresh URL
  4. Check the storage provider's status page for outages

Example fix

# verify the result URL is reachable
status = client.get_job_status(job_id)
url = status["resultUrl"]["jsonUrl"]
import requests
r = requests.get(url, timeout=30)
print(r.status_code, len(r.content))
Defensive patterns

Strategy: retry

Validate before calling

# preflight: is the result storage host reachable?
status = client.get_job_status(job_id)
url = status.get("resultUrl", {}).get("jsonUrl")
if url:
    host = urlparse(url).hostname
    try:
        socket.getaddrinfo(host, 443)
    except socket.gaierror:
        print(f"Result storage host {host} not resolvable — check firewall/DNS")

Try / catch

from paddleocr._api_client.errors import NetworkError
try:
    results = client.get_result(job_id)
except NetworkError:
    time.sleep(3)
    results = client.get_result(job_id)  # pre-signed URL still valid; retry download

Prevention

When it happens

Trigger: client.get_result() where the object-storage host of resultUrl.jsonUrl is unreachable: firewall blocks the storage domain, DNS fails for the CDN bucket, or TLS interception breaks the storage cert.

Common situations: Corporate firewalls whitelisting the API domain but not object storage/CDN domains; egress-restricted containers; regional storage outages; expired pre-signed URLs surfacing as connection-level errors via middleboxes.

Related errors


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