unslothai/unsloth · error · ValueError

local cache path must not contain '..' segments

Error message

local cache path must not contain '..' segments

What it means

Raised by the _check_cache_local_path field validator as a path-traversal guard: the value is parsed both as a POSIX Path and a PureWindowsPath, and if either contains a '..' part it is rejected. Checking both parsers means Windows-style separators (backslashes) are also caught, since PureWindowsPath splits on '\' while Path would treat 'a\..\b' as one segment. This prevents requests from pointing the trainer at caches outside the allowed directory.

Source

Thrown at studio/backend/models/training.py:272

    @field_validator(
        "model_local_path",
        "dataset_local_path",
        "model_snapshot_path",
        "dataset_snapshot_path",
    )
    @classmethod
    def _check_cache_local_path(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return v
        v = v.strip()
        if not v:
            return None
        if len(v) > 4096:
            raise ValueError("local cache path is too long (max 4096 chars)")
        if "\x00" in v:
            raise ValueError("local cache path contains invalid characters")
        if ".." in Path(v).parts or ".." in PureWindowsPath(v).parts:
            raise ValueError("local cache path must not contain '..' segments")
        return v

    @field_validator("train_split", "eval_split")
    @classmethod
    def _check_split_name(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return v
        v = v.strip()
        if not v:
            return None
        if len(v) > MAX_HF_DATASET_OPTION_LENGTH:
            raise ValueError(f"split name is too long (max {MAX_HF_DATASET_OPTION_LENGTH} chars)")
        if not valid_hf_dataset_split_instruction(v):
            raise ValueError("split name contains invalid characters")
        return v

    @field_validator("learning_rate", mode = "before")
    @classmethod

View on GitHub (pinned to 203007d190)

Solutions

  1. Send absolute paths inside the server's cache directory with no '..' segments in either separator style.
  2. If paths are built from user input, sanitize each segment: reject or strip '..' before joining.
  3. Resolve client-side and assert the result stays under the intended cache root.

Example fix

// before
{ model_local_path: `../../shared/model-${id}` }
// after
{ model_local_path: `/cache/models/model-${id}` }
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path, PureWindowsPath

def paths_no_traversal(body: dict) -> bool:
    for f in PATH_FIELDS:
        v = (body.get(f) or "").strip()
        if v and (".." in Path(v).parts or ".." in PureWindowsPath(v).parts):
            return False
    return True

Type guard

function noTraversal(p: string | undefined): boolean {
  if (!p) return true;
  const posix = p.split('/');
  const win = p.split('\\');
  return ![...posix, ...win].includes('..');
}

Prevention

When it happens

Trigger: POST a training start request with any of the four cache-path fields like '../../etc/passwd', 'models/../secrets', or a Windows-style '..\..\data' — the backslash form is caught by the PureWindowsPath check.

Common situations: Relative paths built from user-supplied names that include '..'; a web UI file picker submitting traversal sequences; test/security scans probing the endpoint; path joining where a segment begins with '..'.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/e3151e98606f220e. Report an issue: GitHub.