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

  1. Grant read+execute on the directory to the account running the backend: chmod o+rx (Linux) or adjust ACLs (Windows).
  2. Move or copy the documents into a folder the app user owns.
  3. 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

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


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