unslothai/unsloth · error · ValueError
path may not contain null bytes
Error message
path may not contain null bytes
What it means
Raised by resolve_under_root in storage_roots.py:409-410 when the user-supplied path string contains a NUL byte (\x00). NUL cannot appear in valid filesystem paths on POSIX or Windows and is a common marker of injection attempts or corrupted binary data, so it is rejected before any Path construction.
Source
Thrown at studio/backend/utils/paths/storage_roots.py:409
def resolve_under_root(
path_value: str | None,
*,
root: Path,
strip_prefixes: tuple[str, ...] = (),
) -> Path:
"""Resolve ``path_value`` and assert the result is under ``root``.
Absolutes are accepted only if already contained (so pre-resolved
internal paths re-enter idempotently); schemas reject absolutes upstream.
"""
if not path_value or not str(path_value).strip():
return root
raw = str(path_value).strip()
if "\x00" in raw:
raise ValueError("path may not contain null bytes")
path = Path(raw).expanduser()
if _has_parent_segment(raw, path):
raise ValueError(f"path may not contain '..' segments: {raw!r}")
if _is_absolute_user_path(path):
_assert_contained(path, root)
return path
cleaned = _clean_relative_path(raw, strip_prefixes = strip_prefixes)
candidate = root / cleaned
_assert_contained(candidate, root)
return candidate
def default_run_dir_name(model_name: str) -> str:
# Folder-safe run name for an auto-created output dir. Repo ids keep their
# namespace (org/model -> org_model); local paths (incl. G:\dir\model)View on GitHub (pinned to 203007d190)
Solutions
- Reject or sanitize NUL bytes at the API boundary before paths reach the resolver
- If binary-sourced names are legitimate, strip \x00 and re-validate the result as a safe filename
- Investigate where the NUL entered — usually a decode bug upstream
- Catch ValueError and return a 400 to the client with a clear message
Example fix
# before
name = binary_blob.decode('utf-8', errors='ignore') # may contain \x00
resolve_under_root(name, root=root)
# after
name = binary_blob.decode('utf-8', errors='strict').replace('\x00', '')
assert name and '/' not in name
resolve_under_root(name, root=root) Defensive patterns
Strategy: validation
Validate before calling
def path_has_no_nul(path_str) -> bool:
return "\x00" not in (path_str or "") Type guard
def is_nul_free_path(v: object) -> bool:
return isinstance(v, str) and "\x00" not in v Try / catch
try:
path = resolve_under_root(value, root=root)
except ValueError as exc:
if "null bytes" in str(exc):
raise HTTPException(400, "path contains invalid characters") from exc
raise Prevention
- Reject NUL and other control chars in path fields at the API edge
- Decode binary data strictly (errors='strict') before deriving names
- Fuzz path endpoints; assert they answer 400, not 500
When it happens
Trigger: resolve_under_root("file.bin\x00.txt") — any NUL in the raw string after strip(). Typical sources: binary data decoded as text, crafted API payloads, or truncated buffers leaking NULs into path fields.
Common situations: Fuzzing/security testing of the API; upstream components passing bytes that were decoded with errors='ignore'; copy-pasting from terminals that embed NUL; log/message data accidentally used as filenames.
Related errors
- VirusTotal request failed after {max_attempts} attempt(s): {
- Non-GGUF diffusion loads are restricted to unsloth/* repos (
- base_repo is restricted to unsloth/* repos (or a local path)
- {_cn_fs.reason}
- this torch cannot register the pre-quant constructor allowli
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/2bfe44bfd344dbe9.
Report an issue: GitHub.