unslothai/unsloth · error · ValueError
Invalid transport mode: {mode!r} (transports: {sorted(VALID_
Error message
Invalid transport mode: {mode!r} (transports: {sorted(VALID_TRANSPORTS)}, request modes: {sorted(VALID_TRANSPORT_MODES)}) What it means
Raised by download_registry's cache-preparation layer when `mode` is not one of VALID_TRANSPORTS ({'http','xet'}). Request modes also permit 'auto', but 'auto' must be resolved to a concrete transport before reaching this layer and gets a dedicated error. The message lists both the valid cache transports and the valid request modes to make the mismatch obvious.
Source
Thrown at studio/backend/hub/utils/download_registry.py:776
``protected_blob_hashes`` are blobs a concurrent same-repo peer is writing;
they are excluded from every purge so a shared companion is never deleted
mid-write.
Scope: ``root`` selects the cache captured by the caller. It defaults to the
active ``HF_HUB_CACHE`` root for workers that inherit their cache through
the environment. Markers are written for the new mode before returning,
except when an HTTP purge cannot remove every selected partial. Withholding
the marker keeps the surviving partial untrusted.
"""
if mode not in VALID_TRANSPORTS:
if mode == TRANSPORT_AUTO:
# "auto" is a request preference, not a cache writer: it must be resolved to xet/http
# before reaching this layer. Naming it turns "invalid transport" into the actual bug.
raise ValueError(
f"{TRANSPORT_AUTO!r} must be resolved to a concrete transport before preparing the "
f"cache; expected one of {sorted(VALID_TRANSPORTS)}"
)
raise ValueError(
f"Invalid transport mode: {mode!r} (transports: {sorted(VALID_TRANSPORTS)}, "
f"request modes: {sorted(VALID_TRANSPORT_MODES)})"
)
root = hf_cache_root(create = True) if root is None else hf_cache_root(create = True, root = root)
if root is None:
return 0
target = target_dir_name(repo_type, repo_id)
try:
entries = [e for e in root.iterdir() if e.name.lower() == target]
except OSError:
return 0
if not entries:
# First download: pre-create the repo dir so the marker lands before the
# worker writes any bytes. Otherwise a SIGKILL mid-download leaves a
# partial with no marker that the resume then purges.
canonical = repo_cache_dir_name(repo_type, repo_id)
new_entry = root / canonical
try:View on GitHub (pinned to 203007d190)
Solutions
- Resolve 'auto' to 'http' or 'xet' before calling the cache layer (use the existing resolver used by the download request path).
- Pass exactly 'http' or 'xet' (lowercase) — the set is case-sensitive.
- Validate config early: reject any transport not in {'http','xet','auto'} at settings-load time with a clear message.
Example fix
# before
prepare_cache_for_download(repo, mode='auto')
# after
mode = resolve_transport('auto') # -> 'xet' or 'http'
prepare_cache_for_download(repo, mode=mode) Defensive patterns
Strategy: type-guard
Validate before calling
VALID_TRANSPORTS = {"http", "xet"}
REQUEST_MODES = {"http", "xet", "auto"}
def assert_transport(mode: str) -> str:
if mode == "auto":
return resolve_auto_transport() # existing resolver -> 'http' | 'xet'
if mode not in VALID_TRANSPORTS:
raise ValueError(f"transport must be one of {sorted(VALID_TRANSPORTS)}, got {mode!r}")
return mode Type guard
from typing import Literal
Transport = Literal['http', 'xet']
RequestMode = Literal['http', 'xet', 'auto']
def is_transport(mode: str) -> bool:
return mode in ('http', 'xet') Prevention
- Type transport config as Literal['http','xet'] (request layer may add 'auto') so typos fail at typecheck time.
- Never pass request modes straight to cache-layer APIs; resolve 'auto' first.
- Transport names are case-sensitive and lowercase.
When it happens
Trigger: Calling prepare/purge cache APIs with mode='auto' handled elsewhere, but mode='asyncio', 'hf_transfer', a typo like 'Xet' (case-sensitive), or None reaches this function directly instead of via the request-mode resolution path.
Common situations: New code paths (workers, CLI scripts) built directly on the cache layer and skipping transport resolution; config files carrying a stale or misspelled transport value after an upgrade that split request modes from cache transports.
Related errors
- Add a Provider connection block before running this recipe.
- Unsupported attention_backend '{value}'. Use one of: {', '.j
- Unsupported transformer_cache '{value}'. Use one of: off, au
- too many extra llama-server args (limit {MAX_EXTRA_ARG_TOKEN
- extra llama-server args are too large (limit {limit} bytes)
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/98cd0e9428742aed.
Report an issue: GitHub.