unslothai/unsloth · error · HTTPException

Could not read {os.path.basename(str(current))}

Error message

Could not read {os.path.basename(str(current))}

What it means

Raised as a 500 by _match_browse_child when iterdir() on an intermediate directory fails with a non-permission OSError while the backend walks toward the requested browse path. The full exception is logged with exc_info; the client gets a generic basename-only message so raw OS errors are not leaked.

Source

Thrown at studio/backend/routes/models.py:1644

        if part == ".." or os.sep in part or (altsep and altsep in part):
            return None
    return parts


def _match_browse_child(current: Path, name: str) -> Optional[Path]:
    """Return the immediate child named ``name`` under ``current``."""
    try:
        for child in current.iterdir():
            if child.name == name:
                return child
    except PermissionError:
        raise HTTPException(
            status_code = 403,
            detail = f"Permission denied reading {current.name}",
        ) from None
    except OSError as exc:
        logger.warning("browse-folders: could not read %s: %s", current, exc, exc_info = True)
        raise HTTPException(
            status_code = 500,
            detail = f"Could not read {os.path.basename(str(current))}",
        ) from exc
    return None


def _resolve_browse_target(path: Optional[str], allowed_roots: list[Path]) -> Path:
    """Resolve a requested browse path by walking from trusted allowlist roots."""
    from storage.studio_db import (
        contains_sensitive_path_component,
        is_denied_system_path,
    )

    requested_path = _normalize_browse_request_path(path)
    resolved_roots: list[Path] = []
    seen_roots: set[str] = set()
    for root in sorted(allowed_roots, key = lambda p: len(str(p)), reverse = True):
        try:

View on GitHub (pinned to 203007d190)

Solutions

  1. Check the backend logs — the warning line includes the exact directory and OS error.
  2. Restore the mount/share (reconnect the drive, remount NFS/SMB) and retry.
  3. If a directory was removed, refresh the front-end tree from the allowlist root and re-navigate.
  4. Register a scan folder closer to the data so the walk avoids the failing intermediate directory.
Defensive patterns

Strategy: fallback

Validate before calling

import os

def mount_alive(d: str) -> bool:
    try:
        os.statvfs(d); return True
    except OSError:
        return False

if not mount_alive(models_dir):
    show_user('Storage for this folder is offline — reconnect it, then retry.')

Try / catch

try:
    entries = browse(path)
except HTTPError as e:
    if e.response.status_code == 500 and 'Could not read' in e.response.json()['detail']:
        return fallback_to_cached_entries(path)  # show last-known tree, offer retry
    raise

Prevention

When it happens

Trigger: Browsing a path that traverses an unresponsive network share, a disconnected mapped drive, a stale NFS mount, or a directory deleted mid-walk; ENOENT/EIO/EMFILE-class errors during the component-by-component walk.

Common situations: Mapped drive disconnected on Windows; NFS/SMB server down or timing out; antivirus or filesystem corruption causing EIO; race between directory listing and deletion.

Related errors


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