PaddlePaddle/PaddleOCR · warning · InvalidRequestError

Invalid resource URL: {resource_url}

Error message

Invalid resource URL: {resource_url}

What it means

InvalidRequestError raised when resource_url does not parse as an absolute http(s) URL: the scheme is not http/https or the netloc is empty. It accepts only well-formed absolute web URLs; local paths and other schemes are rejected before any request is made.

Source

Thrown at paddleocr/_api_client/_resources.py:42

from .results import DocParsingResult, OCRResult


def save_resource(
    resource_url: str,
    destination: str,
    *,
    overwrite: bool = False,
    filename: Optional[str] = None,
    timeout: float = 300.0,
) -> str:
    if not resource_url:
        raise InvalidRequestError("resource_url is required.")
    if not destination:
        raise InvalidRequestError("destination is required.")

    parsed_url = urlparse(resource_url)
    if parsed_url.scheme not in ("http", "https") or not parsed_url.netloc:
        raise InvalidRequestError(f"Invalid resource URL: {resource_url}")

    target = _resolve_destination(parsed_url.path, destination, filename)
    _require_writable_target(target, overwrite)

    try:
        response = requests.get(resource_url, timeout=timeout)
    except requests.Timeout as e:
        raise RequestTimeoutError(f"Request timed out: {e}") from e
    except requests.ConnectionError as e:
        raise NetworkError(f"Connection failed: {e}") from e

    try:
        response.raise_for_status()
    except requests.RequestException as e:
        raise NetworkError(f"Failed to download resource: {e}") from e

    _atomic_write(target, response.content, overwrite)
    return str(target)

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Fix the URL: prepend 'https://' when the server returns scheme-less hosts, or resolve relative paths against the API base URL
  2. If you need local/other-scheme sources, download/copy them yourself — save_resource intentionally supports only http(s)
  3. Log the offending URL at the call site to catch malformed values early

Example fix

# before
save_resource(f"{host}{path}", dest)  # host missing scheme -> rejected

# after
if not resource_url.startswith(('http://', 'https://')):
    resource_url = f"https://{resource_url.lstrip('/')}"
save_resource(resource_url, dest)
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse
p = urlparse(resource_url)
assert p.scheme in ('http', 'https') and p.netloc, f'bad resource URL: {resource_url!r}'

Type guard

def is_absolute_http_url(u: str) -> bool:
    p = urlparse(u)
    return p.scheme in ('http', 'https') and bool(p.netloc)

Try / catch

try:
    save_resource(url, dest)
except InvalidRequestError as e:
    if 'Invalid resource URL' in str(e):
        url = f'https://{url}'  # repair scheme-less host and retry once
        save_resource(url, dest)
    else:
        raise

Prevention

When it happens

Trigger: Passing '/tmp/result.json', 'file:///data/img.png', 'ftp://host/f', or a bare 'host/path' (no scheme) to save_resource. Also a URL that got mangled by string formatting (e.g. an f-string that dropped the scheme or left 'None' in place of the host).

Common situations: Result payloads where an image URL is actually a relative path or object-store key rather than a full URL; manually constructed URLs; copy-pasting a path instead of a URL; using an s3:// or gs:// URL where only http(s) is supported.

Related errors


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