unslothai/unsloth · warning · ValueError

Path under {prefix} is not allowed

Error message

Path under {prefix} is not allowed

What it means

Validation error from add_scan_folder_with_status: the normalized path equals or sits under a denied system prefix. The denylist is platform-specific — Linux: /proc, /sys, /dev, /etc, /boot, /run; macOS: /System, /Library, /dev, /etc, /private/etc, /tmp, /private/tmp, /var, /private/var; Windows: SystemRoot, ProgramFiles, ProgramFiles(x86) — with a carve-out letting /run/media/* removable mounts through. Case-insensitive on Windows via os.path.normcase.

Source

Thrown at studio/backend/hub/storage/scan_folders.py:143

        raise ValueError("Path does not exist")
    if not os.path.isdir(normalized):
        raise ValueError("Path must be a directory, not a file")
    if not os.access(normalized, os.R_OK | os.X_OK):
        raise ValueError("Path is not readable")
    if is_local_filesystem_root(normalized):
        # A local fs root ("/", "C:\\") would expose denied system dirs via browse;
        # a UNC share root (\\server\share) has none under it and stays registerable.
        raise ValueError("The filesystem root cannot be registered")
    if _contains_sensitive_path_component(normalized):
        raise ValueError("Credential or configuration directories are not allowed")

    is_win = platform.system() == "Windows"
    check = os.path.normcase(normalized) if is_win else normalized
    for prefix in _denied_path_prefixes():
        if check == prefix or check.startswith(prefix + os.sep):
            if prefix == "/run" and is_linux_run_media_path(check):
                continue
            raise ValueError(f"Path under {prefix} is not allowed")

    conn = get_connection()
    try:
        _ensure_schema(conn)
        now = datetime.now(timezone.utc).isoformat()
        if is_win:
            existing = conn.execute(
                "SELECT id, path, created_at FROM scan_folders WHERE path = ? COLLATE NOCASE",
                (normalized,),
            ).fetchone()
        else:
            existing = conn.execute(
                "SELECT id, path, created_at FROM scan_folders WHERE path = ?",
                (normalized,),
            ).fetchone()
        if existing is not None:
            return dict(existing), False
        inserted = False

View on GitHub (pinned to 203007d190)

Solutions

  1. Move the models to a non-system tree such as /data/models, /srv/models, /home/user/models, or /opt/studio-models (not in the denylist).
  2. On Linux removable media, use /run/media/<user>/<volume>/models which the carve-out allows.
  3. For containerized studio, register a path inside the container's own writable layer or an explicitly mounted data volume.

Example fix

# before
add_scan_folder('/var/lib/studio/models')
# after
add_scan_folder('/srv/studio/models')
Defensive patterns

Strategy: validation

Validate before calling

from storage.scan_folders import is_denied_system_path
import os

def scan_folder_allowed(path: str) -> bool:
    p = os.path.realpath(os.path.expanduser(path.strip()))
    return not is_denied_system_path(p)

Prevention

When it happens

Trigger: Registering /etc/models, /var/lib/models, /tmp/foo, C:\Windows\..., C:\Program Files\..., or any descendant. Registering /run/media/user/USB0/models succeeds (carve-out); /run/systemd fails.

Common situations: Sysadmin-style habits of putting data in /var or /opt-adjacent system trees; Docker/Kubernetes setups where the host /etc is bind-mounted inside the container; macOS users picking /tmp for a quick test.

Related errors


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