{"record":{"id":"051416b46f0d3b20","repo":"sgl-project/sglang","slug":"hugging-face-weight-url-has-no-filename-source-r","errorCode":null,"errorMessage":"Hugging Face weight URL has no filename: {source!r}","messagePattern":"Hugging Face weight URL has no filename: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/weights/source.py","lineNumber":108,"sourceCode":"            revision=revision,\n        )\n    if action not in (\"tree\", \"blob\", \"resolve\") or len(raw_parts) < 4:\n        raise ValueError(f\"Unsupported Hugging Face weight URL: {source!r}\")\n\n    url_revision = unquote(raw_parts[3])\n    selected_revision = _merge_revision(url_revision, revision)\n    tail = \"/\".join(unquote(part) for part in raw_parts[4:])\n    if action == \"tree\":\n        subfolder = _validate_relative_hub_path(tail, \"subfolder\") if tail else None\n        return WeightSource(\n            original=source,\n            kind=\"huggingface\",\n            repo_id=repo_id,\n            revision=selected_revision,\n            subfolder=subfolder,\n        )\n    if not tail:\n        raise ValueError(f\"Hugging Face weight URL has no filename: {source!r}\")\n    return WeightSource(\n        original=source,\n        kind=\"huggingface\",\n        repo_id=repo_id,\n        revision=selected_revision,\n        filename=_validate_relative_hub_path(tail, \"filename\"),\n    )\n\n\ndef parse_weight_source(\n    source: str,\n    *,\n    revision: str | None = None,\n) -> WeightSource:\n    \"\"\"Parse local paths, Hub repo IDs, subfolders, and exact Hub URLs.\"\"\"\n    expanded = os.path.expanduser(source)\n    parsed = urlparse(source)\n    if parsed.scheme in (\"http\", \"https\"):","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/weights/source.py#L90-L126","documentation":"Raised when a Hugging Face URL passed to parse_weight_source resolves to a repo root with no filename component (e.g. https://huggingface.co/owner/repo with no /resolve/.../file path). The parser requires a concrete file path so it can pin an exact weight file. Without a tail the library cannot construct an unambiguous WeightSource.","triggerScenarios":"Calling parse_weight_source (or resolve_weight) with a HF URL whose path ends at the repo or subfolder level, omitting the /revision/resolve/<rev>/<path> or /blob/<rev>/<path> suffix.","commonSituations":"Copy-pasting a repo page URL instead of a file URL from the HF website; constructing URLs programmatically and forgetting the filename segment.","solutions":["Append the file path to the URL, e.g. https://huggingface.co/owner/repo/resolve/main/model.safetensors","If you mean the whole repo or a subfolder, pass the plain 'owner/repo' or 'owner/repo/subfolder' reference instead of a URL"],"exampleFix":"# before\nparse_weight_source(\"https://huggingface.co/org/repo\")\n# after\nparse_weight_source(\"https://huggingface.co/org/repo/resolve/main/model.safetensors\")","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef hf_url_has_filename(url: str) -> bool:\n    parts = [p for p in urlparse(url).path.split(\"/\") if p]\n    # expect owner/repo/(resolve|blob)/rev/file...\n    return len(parts) >= 5","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always copy the full file URL from the HF Files page including /resolve/<rev>/","Pre-validate URL structure before calling parse_weight_source"],"tags":["huggingface","weights","url-parsing"],"backgroundTag":"invalid-url-format","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}