unslothai/unsloth · warning · ValueError

Path must be a directory, not a file

Error message

Path must be a directory, not a file

What it means

Validation error from add_scan_folder_with_status: the path exists but os.path.isdir() is False — a regular file was submitted. Scan folders must be directories because the inventory walks them for model weights.

Source

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

        _ensure_schema(conn)
        rows = conn.execute(
            "SELECT id, path, created_at FROM scan_folders ORDER BY created_at"
        ).fetchall()
        return [dict(row) for row in rows]
    finally:
        conn.close()


def add_scan_folder_with_status(path: str) -> tuple[dict, bool]:
    """Add a readable scan folder and return its row plus whether it was inserted."""
    if not path or not path.strip():
        raise ValueError("Path cannot be empty")
    normalized = os.path.realpath(os.path.expanduser(normalize_path(path.strip())))

    if not os.path.exists(normalized):
        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()

View on GitHub (pinned to 203007d190)

Solutions

  1. Register the containing directory instead of the file.
  2. If the intent was to point at one model, use the model-path/custom-folder mechanism that accepts weight files, not scan folders.

Example fix

# before
add_scan_folder('/data/models/llama.gguf')
# after
add_scan_folder('/data/models')
Defensive patterns

Strategy: validation

Validate before calling

import os

def is_registerable_dir(path: str) -> bool:
    p = os.path.realpath(os.path.expanduser(path.strip()))
    return os.path.isdir(p)

Prevention

When it happens

Trigger: Registering a file like /data/models/model.gguf or /home/user/config.yaml as a scan folder.

Common situations: Users pasting the path to a downloaded weight file instead of its folder; drag-and-drop from a file manager yielding a file path; confusion between scan folders (directories) and model weight files (accepted elsewhere).

Related errors


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