unslothai/unsloth · error · ValueError
path may not contain '..' segments: {raw!r}
Error message
path may not contain '..' segments: {raw!r} What it means
Raised by resolve_under_root in storage_roots.py:412-414 when the path contains a '..' parent segment (checked textually on the raw string and via the expanded Path). This blocks trivial traversal like '../../etc/passwd' before any root joining; on Windows both '..' and '..'-style backslash forms are caught by the segment check.
Source
Thrown at studio/backend/utils/paths/storage_roots.py:413
*,
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)
# collapse to their final component so an absolute source can't escape
# outputs_root. Length-capped to stay under the filesystem name limit.
raw = str(model_name or "").strip()
is_path = (View on GitHub (pinned to 203007d190)
Solutions
- Normalize client-side first: send a clean relative path without traversal segments
- If you must accept user trees, use pathlib's Path.parts to filter out '..' before calling
- Pass absolute paths only if they are already known to be contained (the resolver accepts contained absolutes idempotently)
- Catch ValueError and map it to a validation error message for the user
Example fix
# before
resolve_under_root("../../secret.txt", root=root)
# after
from pathlib import PurePosixPath
rel = PurePosixPath(user_path)
if '..' in rel.parts:
raise HTTPException(400, 'relative paths may not contain ..')
resolve_under_root(str(rel), root=root) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import PurePath
def has_parent_segment(path_str: str) -> bool:
return ".." in PurePath(path_str.strip()).parts or ".." in path_str.split("/") Type guard
def is_traversal_free_path(v: object) -> bool:
if not isinstance(v, str):
return False
return ".." not in PurePath(v.strip()).parts Try / catch
try:
path = resolve_under_root(value, root=root)
except ValueError as exc:
if "'..' segments" in str(exc):
raise HTTPException(400, "relative paths may not contain ..") from exc
raise Prevention
- Filter '..' out of Path.parts on untrusted paths before submission
- Send canonical relative paths (no up-walking) from clients
- Reject traversal at request-schema validation, before filesystem code
When it happens
Trigger: resolve_under_root("../../etc/passwd", root=...) or "models/../.." — any '..' segment in the stripped raw string or the expandeduser path. Note the check is on segments, so a filename literally containing '..' as a whole segment ("..") triggers, while '..hidden' does not.
Common situations: Clients sending relative paths built by naive joining that walk up; security probing; user-typed paths in an export/save dialog containing '..'; reusing external relative paths (e.g. from a zip or git) that assume a different working root.
Related errors
- dataset path may not contain null bytes
- dataset path may not contain '..' segments: {raw!r}
- save_directory may not contain null bytes
- save_directory may not contain '..' segments
- hf_dataset must not contain '..'
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/387293534ea8947d.
Report an issue: GitHub.