roboflow/supervision · error · ValueError

prepared URL is empty

Error message

prepared URL is empty

What it means

Raised during URL validation when `requests.Request(...).prepare()` produces a request whose `.url` is None. This is a defensive branch: normally PrepareRequest always yields a URL string, so hitting this means the input was degenerate enough (e.g. None or an empty/non-string value coerced through preparation) that no URL could be formed.

Source

Thrown at src/supervision/utils/file.py:37

    Args:
        url: URL to validate.

    Returns:
        Normalized URL string.

    Raises:
        ValueError: If the URL is invalid or uses an unsupported scheme.
    """
    try:
        original_parsed_url = urllib.parse.urlparse(url)
        if "\\" in original_parsed_url.netloc:
            raise ValueError("URL authority contains a backslash")

        prepared_request = requests.Request(method="GET", url=url).prepare()
        prepared_url = prepared_request.url
        if prepared_url is None:
            raise ValueError("prepared URL is empty")

        parsed_url = urllib.parse.urlparse(prepared_url)
    except (requests.RequestException, ValueError) as error:
        raise ValueError(f"Invalid URL {url!r}: {error}") from error

    if parsed_url.scheme not in {"http", "https"}:
        raise ValueError(
            f"Unsupported URL scheme {parsed_url.scheme!r} in {url!r}. "
            "Only HTTP and HTTPS URLs are supported."
        )
    if parsed_url.hostname is None:
        raise ValueError(f"Invalid URL {url!r}: no host supplied.")

    return prepared_url


def _download_to_file(
    url: str, target: Path, *, timeout: float = 30.0, stream: bool = False

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Check the value is a non-empty string before calling: `if not url: raise` early with your own message.
  2. Default optional URLs explicitly and skip the download when absent.
  3. Log the raw input when validation fails to identify which field produced None.

Example fix

# before
url = config.get('weights_url')  # may be None
download(url)
# after
url = config.get('weights_url')
if not url:
    raise ValueError('weights_url is required')
download(url)
Defensive patterns

Strategy: validation

Validate before calling

assert isinstance(url, str) and url.strip(), f'url must be a non-empty string, got {url!r}'

Type guard

def is_nonempty_str(url: Any) -> bool:
    return isinstance(url, str) and bool(url.strip())

Prevention

When it happens

Trigger: Passing `None` or `''` as the url; passing an object whose `__str__`/preparation yields no URL; unusual requests versions or objects where `prepare()` leaves url unset.

Common situations: Optional config fields defaulting to None and forwarded unchecked; f-string URL construction from all-empty parts; duck-typed wrappers passing their own objects instead of strings.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/f2f8a58451b4811a. Report an issue: GitHub.