sgl-project/sglang · error · ValueError

Invalid Hugging Face

Error message

Invalid Hugging Face {field_name}: {path!r}

What it means

Raised by _validate_relative_hub_path (via _parse_huggingface_url / parse_weight_source) when a subfolder or filename extracted from a Hugging Face URL is empty, absolute, or contains '..'. Only safe, relative, normalized paths are accepted as hub subpaths.

Solutions

  1. Remove '..' segments and leading slashes from the URL subpath
  2. Point at a real subfolder/file path inside the repo, or drop the subfolder part entirely
  3. Alternatively use a local path plus an explicit subfolder argument instead of a crafted URL

Example fix

# before
parse_weight_source("https://huggingface.co/org/repo/tree/main/../diffusers")
# after
parse_weight_source("https://huggingface.co/org/repo/tree/main/diffusers")
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import PurePosixPath
def safe_hub_subpath(p: str) -> bool:
    pp = PurePosixPath(str(p))
    return bool(p) and not pp.is_absolute() and ".." not in pp.parts

Type guard

def is_valid_hub_path(path: str) -> bool:
    pp = PurePosixPath(path)
    return bool(path) and not path.startswith("/") and ".." not in path.split("/")

Try / catch

try:
    src = parse_weight_source(url)
except ValueError as e:
    if "Invalid Hugging Face" in str(e):
        src = parse_weight_source(sanitize(url))
    else:
        raise

Prevention

When it happens

Trigger: parse_weight_source on a URL like https://huggingface.co/repo/tree//sub or one containing '..' segments (e.g. /repo/tree/main/../secret), or an unquoted path that normalizes to empty.

Common situations: Hand-editing weight URLs, copy-pasting URLs with traversal segments, or programmatically joining subfolder paths that accidentally produce '..' or leading '/'.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/7647efb450c5f27b. Report an issue: GitHub.

Appendix: source

Thrown at python/sglang/multimodal_gen/runtime/weights/source.py:55

@dataclass(frozen=True)
class ResolvedWeight:
    inventory: WeightInventory
    selected_file: str


def is_explicit_weight_file_reference(source: str) -> bool:
    """Whether a component override names one weight file, not a component root."""
    expanded = os.path.expanduser(source)
    if os.path.isdir(expanded):
        return False
    return urlparse(source).path.lower().endswith(_WEIGHT_SUFFIXES)


def _validate_relative_hub_path(path: str, field_name: str) -> str:
    normalized = str(PurePosixPath(path))
    pure_path = PurePosixPath(normalized)
    if not path or pure_path.is_absolute() or ".." in pure_path.parts:
        raise ValueError(f"Invalid Hugging Face {field_name}: {path!r}")
    return normalized


def _merge_revision(url_revision: str | None, revision: str | None) -> str | None:
    if url_revision is not None and revision is not None and url_revision != revision:
        raise ValueError(
            f"Weight URL pins revision {url_revision!r}, which conflicts with "
            f"revision {revision!r}"
        )
    return url_revision or revision


def _parse_huggingface_url(source: str, revision: str | None) -> WeightSource:
    parsed = urlparse(source)
    if parsed.netloc.lower() not in ("huggingface.co", "www.huggingface.co"):
        raise ValueError(
            "Only huggingface.co weight URLs are supported; use a local path "
            "or an owner/repo reference for other sources"

View on GitHub (pinned to 0132848349)