unslothai/unsloth · warning · ValueError
dataset path may not contain '..' segments: {raw!r}
Error message
dataset path may not contain '..' segments: {raw!r} What it means
Traversal guard in resolve_dataset_path: after normalize_path (which converts backslashes so Windows-style '..\' can't slip through) and expanduser, the Path's parts still contain a '..' segment. '..' would let a relative dataset path escape its intended root when joined, so any occurrence is rejected outright — resolution to a root happens only after this check.
Source
Thrown at studio/backend/hub/utils/paths.py:399
"""
try:
path_real = os.path.normcase(os.path.realpath(str(path)))
root_real = os.path.normcase(os.path.realpath(str(root)))
return os.path.commonpath([path_real, root_real]) == root_real
except (OSError, ValueError):
return False
def resolve_dataset_path(path_value: str) -> Path:
raw = str(path_value or "").strip()
if "\x00" in raw:
raise ValueError("dataset path may not contain null bytes")
# Normalize first so Windows/UNC and backslash paths resolve like the rest of the Hub path
# layer, and a backslashed '..' is caught by the traversal guard below.
normalized = normalize_path(raw)
path = Path(normalized).expanduser()
if ".." in path.parts:
raise ValueError(f"dataset path may not contain '..' segments: {raw!r}")
if path.is_absolute():
for root in (datasets_root(), dataset_uploads_root(), recipe_datasets_root()):
try:
_assert_contained(path, root)
return path
except ValueError:
continue
raise ValueError(f"dataset path must be relative or under a dataset root: {raw!r}")
parts = [part for part in Path(normalized).parts if part not in ("", ".")]
if parts[:2] == ["assets", "datasets"]:
parts = parts[2:]
if parts and parts[0] == "uploads":
cleaned = Path(*parts[1:]) if len(parts) > 1 else Path()
return dataset_uploads_root() / cleaned
if parts and parts[0] == "recipes":
cleaned = Path(*parts[1:]) if len(parts) > 1 else Path()
return recipe_datasets_root() / cleanedView on GitHub (pinned to 203007d190)
Solutions
- Reference the target by its own path under the dataset root, without '..' — e.g. 'shared/data.csv' if that is its logical location.
- If the caller has an arbitrary user path, resolve it to an absolute path first and check containment against the dataset root instead of embedding '..'.
- Escape/normalize user input client-side and reject '..' segments before submission.
Example fix
# before
resolve_dataset_path('uploads/../../etc/passwd')
# after
resolve_dataset_path('uploads/mydata.csv') # stay inside the dataset root Defensive patterns
Strategy: validation
Validate before calling
def has_dotdot(path_value: str) -> bool:
return ".." in Path((path_value or "").strip().replace("\\", "/")).parts Try / catch
try:
p = resolve_dataset_path(value)
except ValueError as e:
if "'..'" in str(e):
return bad_request("dataset path must not contain '..' — use a path under the dataset root") Prevention
- Normalize separators before inspecting parts — backslash '..\\' is converted by the API, do the same client-side.
- Map user-chosen files to logical dataset-relative paths instead of passing raw OS paths.
- Remember literal '..' text is rejected even if it would resolve somewhere safe.
When it happens
Trigger: Passing 'assets/datasets/../../secrets.txt', 'uploads/../config', or '..\..\windows\system32' to a dataset path resolution API; a UI file picker that returns relative paths with parent segments.
Common situations: Path-traversal attempts (../../../../etc/passwd); legitimate users trying to reference a sibling directory ('../shared/data.csv'); symlinks are fine but literal '..' text is not.
Related errors
- dataset path may not contain null bytes
- dataset path must be relative or under a dataset root: {raw!
- 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/d71356ecac1ffc7e.
Report an issue: GitHub.