roboflow/supervision · error · ValueError

Invalid URL {url}: no host supplied.

Error message

Invalid URL {url}: no host supplied.

What it means

Raised during URL validation when the URL parses successfully but `parsed_url.hostname` is None — the authority component has no host. This catches inputs like 'http:///path' (empty host) or scheme-only strings where nothing addressable remains after normalization by `requests.Request.prepare()`.

Source

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

        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
) -> None:
    """
    Download `url` to `target` atomically using a temporary file and `os.replace`.

    Args:
        url: HTTP(S) URL to download.
        target: Destination file path. Parent directories are created as needed.
        timeout: Request timeout in seconds. Defaults to `30.0`.
        stream: If `True`, stream the response to disk in chunks and display a
            progress bar. If `False`, buffer the response in memory before
            writing. Defaults to `False`.

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Fix the URL to include a host: 'http://example.com/data/file'.
  2. If the host comes from config, validate it is non-empty before building the URL string.
  3. Log the final URL before passing it to catch template bugs early.

Example fix

# before
url = f'http://{os.environ.get("HOST")}/file'  # HOST unset -> 'http:///file'
# after
host = os.environ['HOST']
url = f'http://{host}/file'
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse
assert urlparse(url).hostname, f'URL has no host: {url}'

Type guard

def url_has_host(url: str) -> bool:
    return urlparse(url).hostname is not None

Prevention

When it happens

Trigger: Passing `'http:///data/file'` (triple slash, empty host); `'http://'` alone; a URL built by string concatenation where the host variable was empty, e.g. `f'http://{host}/f'` with `host=''`.

Common situations: Templating URLs from environment variables where the host var is unset; string-built URLs with a missing host segment; copy-paste errors dropping the domain.

Related errors


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