unslothai/unsloth · warning · ValueError
Path is not readable
Error message
Path is not readable
What it means
ValueError raised when os.access(normalized, R_OK | X_OK) fails: the process cannot read entries in or traverse into the directory. Even a valid directory is useless as a scan root if the app cannot list and descend into it, so the policy rejects it up front. The check runs as the app's effective UID, so root-owned or restricted directories fail here rather than producing empty or partial indexes.
Source
Thrown at studio/backend/core/rag/folder_sync.py:150
if stat.S_ISLNK(os.lstat(expanded).st_mode):
raise ValueError("Symbolic-link folders are not allowed")
except OSError as exc:
raise ValueError("Path does not exist") from exc
normalized = os.path.realpath(expanded)
uploads_root = os.path.realpath(str(rag_uploads_root()))
if _paths_overlap(_path_key(normalized), _path_key(uploads_root)):
raise ValueError("The managed RAG uploads folder cannot be linked")
from hub.storage.scan_folders import (
contains_sensitive_path_component,
is_denied_system_path,
)
from utils.paths.external_media import is_local_filesystem_root
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):
raise ValueError("The filesystem root cannot be registered")
try:
if Path(normalized) == Path.home().resolve():
raise ValueError("The entire home folder cannot be registered")
except RuntimeError:
pass
if contains_sensitive_path_component(normalized):
raise ValueError("Credential or configuration directories are not allowed")
if is_denied_system_path(normalized):
raise ValueError("System directories are not allowed")
return normalized
def _root_identity(root: str) -> tuple[int, int]:
try:
root_stat = os.lstat(root)
except OSError as exc:View on GitHub (pinned to 203007d190)
Solutions
- Grant read+execute on the directory to the account running the backend: chmod o+rx (Linux) or adjust ACLs (Windows).
- Move or copy the documents into a folder the app user owns.
- Run the backend as a user with access to the share, or mount the share with credentials for that user.
Example fix
# before chmod 700 /srv/docs # only owner can enter; backend runs as different user # after chmod 755 /srv/docs # backend user can read and traverse
Defensive patterns
Strategy: validation
Validate before calling
import os
def folder_readable(path: str) -> bool:
expanded = os.path.realpath(os.path.abspath(os.path.expanduser(path)))
return os.path.isdir(expanded) and os.access(expanded, os.R_OK | os.X_OK) Try / catch
try:
validate_folder_path(path)
except ValueError as e:
if str(e) != "Path is not readable":
raise
return bad_request("grant the app read+traverse permission on that folder") Prevention
- Run the backend under a user/group with read access to all registered sources.
- In containers, chown/bind-mount host folders to match the container UID.
- Pre-flight os.access checks in deployment scripts for each folder you plan to register.
When it happens
Trigger: Registering a directory owned by another user with mode 700; a directory on a FUSE mount that denies the app's user; running the backend as a service account with a restricted umask/home; Windows ACLs denying the service account traversal.
Common situations: Docker containers where the host folder is owned by a UID different from the container user; system directories like /root or other users' homes; NAS mounts with restrictive permissions; services running as 'nobody'.
Related errors
- Path does not exist
- Path must be a directory, not a file
- The filesystem root cannot be registered
- local cache path is too long (max 4096 chars)
- Studio does not have permission to write to this folder.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/c4bc0fb95f1c4c98.
Report an issue: GitHub.