{"record":{"id":"28c1d727b82d0981","repo":"roboflow/supervision","slug":"invalid-url-url-no-host-supplied","errorCode":null,"errorMessage":"Invalid URL {url}: no host supplied.","messagePattern":"Invalid URL (.+?): no host supplied\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/utils/file.py","lineNumber":49,"sourceCode":"        if \"\\\\\" in original_parsed_url.netloc:\n            raise ValueError(\"URL authority contains a backslash\")\n\n        prepared_request = requests.Request(method=\"GET\", url=url).prepare()\n        prepared_url = prepared_request.url\n        if prepared_url is None:\n            raise ValueError(\"prepared URL is empty\")\n\n        parsed_url = urllib.parse.urlparse(prepared_url)\n    except (requests.RequestException, ValueError) as error:\n        raise ValueError(f\"Invalid URL {url!r}: {error}\") from error\n\n    if parsed_url.scheme not in {\"http\", \"https\"}:\n        raise ValueError(\n            f\"Unsupported URL scheme {parsed_url.scheme!r} in {url!r}. \"\n            \"Only HTTP and HTTPS URLs are supported.\"\n        )\n    if parsed_url.hostname is None:\n        raise ValueError(f\"Invalid URL {url!r}: no host supplied.\")\n\n    return prepared_url\n\n\ndef _download_to_file(\n    url: str, target: Path, *, timeout: float = 30.0, stream: bool = False\n) -> None:\n    \"\"\"\n    Download `url` to `target` atomically using a temporary file and `os.replace`.\n\n    Args:\n        url: HTTP(S) URL to download.\n        target: Destination file path. Parent directories are created as needed.\n        timeout: Request timeout in seconds. Defaults to `30.0`.\n        stream: If `True`, stream the response to disk in chunks and display a\n            progress bar. If `False`, buffer the response in memory before\n            writing. Defaults to `False`.\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/utils/file.py#L31-L67","documentation":"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()`.","triggerScenarios":"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=''`.","commonSituations":"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.","solutions":["Fix the URL to include a host: 'http://example.com/data/file'.","If the host comes from config, validate it is non-empty before building the URL string.","Log the final URL before passing it to catch template bugs early."],"exampleFix":"# before\nurl = f'http://{os.environ.get(\"HOST\")}/file'  # HOST unset -> 'http:///file'\n# after\nhost = os.environ['HOST']\nurl = f'http://{host}/file'","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\nassert urlparse(url).hostname, f'URL has no host: {url}'","typeGuard":"def url_has_host(url: str) -> bool:\n    return urlparse(url).hostname is not None","tryCatchPattern":null,"preventionTips":["Validate templated host variables are non-empty before building URLs.","Log the final URL string before passing it downstream.","Add a startup sanity check for URLs assembled from env vars."],"tags":["url","download","validation","hostname"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}