unslothai/unsloth · warning · ValueError
dataset path must be relative or under a dataset root: {raw!
Error message
dataset path must be relative or under a dataset root: {raw!r} What it means
Raised by resolve_dataset_path when the input is an absolute path that is not contained in any of the accepted roots (datasets_root, dataset_uploads_root, recipe_datasets_root, checked via realpath+commonpath). Absolute paths are only honored when they already live under a managed dataset root; everything else — /etc/passwd, /home/user/data — is refused. Relative paths and the 'uploads/'/'recipes' virtual prefixes are handled by later branches.
Source
Thrown at studio/backend/hub/utils/paths.py:407
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() / cleaned
cleaned = Path(*parts) if parts else Path()
candidates = [
dataset_uploads_root() / cleaned,
recipe_datasets_root() / cleaned,
datasets_root() / cleaned,
dataset_uploads_root() / cleaned.name,
recipe_datasets_root() / cleaned.name,View on GitHub (pinned to 203007d190)
Solutions
- Use a relative path or the logical prefixes: 'mydata.csv', 'uploads/...', or 'recipes/...'.
- If an absolute path is required, place the data under one of the dataset roots (or reconfigure the root to cover the location) and ensure symlinks resolve inside it.
- Check for symlink escape: `realpath <path>` must start with one of the configured dataset roots.
Example fix
# before
resolve_dataset_path('/home/alice/my.csv')
# after
resolve_dataset_path('my.csv') # resolved under datasets_root() Defensive patterns
Strategy: validation
Validate before calling
from hub.utils.paths import datasets_root, dataset_uploads_root, recipe_datasets_root
def absolute_dataset_path_ok(path: str) -> bool:
p = Path(path).expanduser()
if not p.is_absolute():
return True
pr = Path(os.path.realpath(p))
return any(
os.path.commonpath([pr, os.path.realpath(str(r))]) == os.path.realpath(str(r))
for r in (datasets_root(), dataset_uploads_root(), recipe_datasets_root())
) Try / catch
try:
p = resolve_dataset_path(value)
except ValueError as e:
if "relative or under a dataset root" in str(e):
return bad_request("use a relative dataset path like 'uploads/file.csv'") Prevention
- Prefer relative paths and the uploads//recipes/ virtual prefixes over absolute paths.
- Remember containment is checked on realpath — symlinks escaping the root are rejected too.
- After moving dataset roots, re-issue stored absolute paths as relative ones.
When it happens
Trigger: Calling a dataset API with '/home/alice/my.csv' (outside all roots) or '/var/data/d.csv'; also fires when a path that looks contained is actually a symlink whose realpath resolves outside every root (commonpath uses realpath).
Common situations: Users pasting local absolute paths where a logical dataset-relative path is expected; moved/renamed dataset roots so previously-valid absolute paths no longer resolve inside; symlinked data dirs that point elsewhere.
Related errors
- The filesystem root cannot be registered
- Path under {prefix} is not allowed
- dataset path may not contain null bytes
- dataset path may not contain '..' segments: {raw!r}
- {_cn_fs.reason}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/df3b4ea75e0f0b47.
Report an issue: GitHub.