unslothai/unsloth · warning · ValueError
Path is not readable
Error message
Path is not readable
What it means
Validation error from add_scan_folder_with_status: os.access(normalized, os.R_OK | os.X_OK) reports the backend process cannot read or traverse the directory. The folder may be browsable by another user but not by the account running studio, since os.access uses the real (not effective-filesystemACL) view of the current process.
Source
Thrown at studio/backend/hub/storage/scan_folders.py:129
"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()
try:
_ensure_schema(conn)View on GitHub (pinned to 203007d190)
Solutions
- Grant read+execute to the service user: `chmod o+rx /data/models` or chown/chgrp to the backend group.
- Verify as that user: `sudo -u <backend-user> test -r <path> -a -x <path> && echo ok`.
- Move the models under a shared location both users can access.
Example fix
# before: /home/alice/models is 0700, backend runs as 'studio' sudo chmod o+rx /home/alice /home/alice/models # after: backend can register /home/alice/models
Defensive patterns
Strategy: validation
Validate before calling
import os
def backend_can_read(path: str) -> bool:
p = os.path.realpath(os.path.expanduser(path.strip()))
return os.path.isdir(p) and os.access(p, os.R_OK | os.X_OK) Prevention
- Run the os.access check as the service user, not your own account.
- Grant r+x on every parent component, not just the leaf directory.
- For systemd services, avoid DynamicUser/restrictive User= for hosts holding model data.
When it happens
Trigger: Registering a 0700 directory owned by another user; a directory with mode 0600; running the backend under a restricted systemd user (DynamicUser) that lacks access to /home/*.
Common situations: Models stored in another user's home; permission tightening after a security pass; backend running as 'nobody'; directories on media mounted with permissions that exclude the service user.
Related errors
- Path is not readable
- Path cannot be empty
- Path does not exist
- Path must be a directory, not a file
- The filesystem root cannot be registered
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/3390b2a2b31981d2.
Report an issue: GitHub.