unslothai/unsloth · error · ValueError
path resolution failed: {exc}
Error message
path resolution failed: {exc} What it means
Raised by _assert_contained in studio/backend/utils/paths/storage_roots.py:384-385 when os.path.realpath() raises OSError while resolving either the candidate path or the storage root. This is an environment-level failure (permissions, stale file handles, path encoding problems), not a validation failure; the error message embeds the underlying OS error.
Source
Thrown at studio/backend/utils/paths/storage_roots.py:384
if ".." in PureWindowsPath(raw).parts:
return True
return ".." in raw.replace("\\", "/").split("/")
def _is_absolute_user_path(path: Path) -> bool:
expanded = str(path)
if os.name == "nt":
return path.is_absolute() and PureWindowsPath(expanded).is_absolute()
return path.is_absolute() and PurePosixPath(expanded).is_absolute()
def _assert_contained(resolved: Path, root: Path) -> None:
"""Raise ValueError if ``resolved`` realpaths outside ``root``."""
try:
resolved_real = Path(os.path.realpath(resolved))
root_real = Path(os.path.realpath(root))
except OSError as exc:
raise ValueError(f"path resolution failed: {exc}") from exc
try:
resolved_real.relative_to(root_real)
except ValueError as exc:
raise ValueError(
f"path escapes root: {resolved!s} -> {resolved_real!s} " f"is not under {root_real!s}"
) from exc
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.View on GitHub (pinned to 203007d190)
Solutions
- Check the underlying OSError (__cause__) for errno: EACCES -> fix permissions, ELOOP -> break the symlink cycle, ENOENT -> the root may be gone
- Verify the storage root exists and is readable before resolving paths under it
- Remove or repair symlink loops in or under the root
- If the volume is removable, re-mount it and retry the operation
Example fix
# before
path = resolve_under_root(user_input, root=exports_root())
# after
import errno
try:
path = resolve_under_root(user_input, root=exports_root())
except ValueError as exc:
cause = exc.__cause__
if cause and cause.errno == errno.EACCES:
raise PermissionError(str(cause)) from cause
raise Defensive patterns
Strategy: try-catch
Validate before calling
def root_accessible(root) -> bool:
try:
root_real = Path(os.path.realpath(root))
return root_real.exists() and os.access(root_real, os.R_OK | os.X_OK)
except OSError:
return False Try / catch
import errno
try:
path = resolve_under_root(value, root=root)
except ValueError as exc:
cause = exc.__cause__
if isinstance(cause, OSError):
if cause.errno in (errno.EACCES, errno.EPERM):
raise HTTPException(403, "storage root not accessible") from exc
if cause.errno == errno.ELOOP:
raise HTTPException(400, "symlink loop under storage root") from exc
raise HTTPException(503, "storage root unavailable") from exc
raise Prevention
- Health-check the storage root (exists + readable) at startup and before batch jobs
- Avoid symlink cycles under storage roots
- Surface the chained OSError errno in logs for fast triage
- Mount external volumes directly, not via fragile symlink chains
When it happens
Trigger: resolve_under_root called with a path whose realpath traversal hits an unreadable directory (EACCES), a broken symlink loop (ELOOP), or a path with invalid encoding on the platform. Also when the storage root itself becomes inaccessible (unmounted drive, deleted directory).
Common situations: Storage root on a disconnected network drive or removable volume on Windows; permission changes mid-session; symlink cycles created by users; deeply nested paths exceeding OS limits.
Related errors
- Invalid path
- Execution artifacts are no longer available.
- Execution artifact path is not a dataset folder.
- GGUF conversion produced a symlink, refusing to relocate it:
- Local base_repo is not a diffusers pipeline directory (no {i
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/c53bc24d40452041.
Report an issue: GitHub.