{"record":{"id":"f2f8a58451b4811a","repo":"roboflow/supervision","slug":"prepared-url-is-empty","errorCode":null,"errorMessage":"prepared URL is empty","messagePattern":"prepared URL is empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/utils/file.py","lineNumber":37,"sourceCode":"\n    Args:\n        url: URL to validate.\n\n    Returns:\n        Normalized URL string.\n\n    Raises:\n        ValueError: If the URL is invalid or uses an unsupported scheme.\n    \"\"\"\n    try:\n        original_parsed_url = urllib.parse.urlparse(url)\n        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","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/utils/file.py#L19-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the value is a non-empty string before calling: `if not url: raise` early with your own message.","Default optional URLs explicitly and skip the download when absent.","Log the raw input when validation fails to identify which field produced None."],"exampleFix":"# before\nurl = config.get('weights_url')  # may be None\ndownload(url)\n# after\nurl = config.get('weights_url')\nif not url:\n    raise ValueError('weights_url is required')\ndownload(url)","handlingStrategy":"validation","validationCode":"assert isinstance(url, str) and url.strip(), f'url must be a non-empty string, got {url!r}'","typeGuard":"def is_nonempty_str(url: Any) -> bool:\n    return isinstance(url, str) and bool(url.strip())","tryCatchPattern":null,"preventionTips":["Fail fast on None/empty optional URL fields with your own clear error.","Do not forward unchecked config.get() results into downloaders.","Default optional URLs to None and branch explicitly."],"tags":["url","download","validation","none-check"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}