{"record":{"id":"2724e1526c474a3d","repo":"unslothai/unsloth","slug":"permission-denied-reading-current-name","errorCode":null,"errorMessage":"Permission denied reading {current.name}","messagePattern":"Permission denied reading (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"studio/backend/routes/models.py","lineNumber":1638,"sourceCode":"    if rel_text == \"..\" or rel_text.startswith(f\"..{os.sep}\"):\n        return None\n\n    parts = [part for part in rel_text.split(os.sep) if part not in (\"\", \".\")]\n    altsep = os.altsep\n    for part in parts:\n        if part == \"..\" or os.sep in part or (altsep and altsep in part):\n            return None\n    return parts\n\n\ndef _match_browse_child(current: Path, name: str) -> Optional[Path]:\n    \"\"\"Return the immediate child named ``name`` under ``current``.\"\"\"\n    try:\n        for child in current.iterdir():\n            if child.name == name:\n                return child\n    except PermissionError:\n        raise HTTPException(\n            status_code = 403,\n            detail = f\"Permission denied reading {current.name}\",\n        ) from None\n    except OSError as exc:\n        logger.warning(\"browse-folders: could not read %s: %s\", current, exc, exc_info = True)\n        raise HTTPException(\n            status_code = 500,\n            detail = f\"Could not read {os.path.basename(str(current))}\",\n        ) from exc\n    return None\n\n\ndef _resolve_browse_target(path: Optional[str], allowed_roots: list[Path]) -> Path:\n    \"\"\"Resolve a requested browse path by walking from trusted allowlist roots.\"\"\"\n    from storage.studio_db import (\n        contains_sensitive_path_component,\n        is_denied_system_path,\n    )","sourceCodeStart":1620,"sourceCodeEnd":1656,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/models.py#L1620-L1656","documentation":"Raised as a 403 by _match_browse_child when the backend, while walking from an allowlist root toward the requested browse path, hits a PermissionError calling iterdir() on an intermediate directory. It means the backend process lacks read permission on that directory, so it cannot confirm the next path component exists.","triggerScenarios":"GET browse-folders with a path whose route from an allowed root passes through a directory owned by another user or with mode 700; running the studio backend as a user without read access; Windows ACLs denying list permission on a parent folder.","commonSituations":"Models stored under a sibling user's home or a restricted mount; containerized backend running as a different uid than the directory owner; macOS/Linux permission tightening on parent dirs.","solutions":["Grant the backend process read+execute permission on the blocking directory: chmod a+rx /restricted/dir or adjust the ACL.","Run the backend as a user that can traverse the path, or move the models under a directory the backend can read.","Register the deepest readable directory as a scan folder via POST /api/models/scan-folders so the walk starts there and skips unreadable parents."],"exampleFix":"# before: walk must pass through /srv/private (mode 700, other user)\nGET /api/models/browse-folders?path=/srv/private/models  # 403\n\n# after (backend user can traverse):\n# chmod o+rx /srv/private\nGET /api/models/browse-folders?path=/srv/private/models","handlingStrategy":"validation","validationCode":"import os\n\ndef readable(d: str) -> bool:\n    try:\n        os.listdir(d); return True\n    except PermissionError:\n        return False\n\npath = '/srv/private/models'\nif not all(readable(p) for p in iter_parents(path)):\n    raise PermissionError('backend cannot traverse path — fix perms or register a nearer scan folder')","typeGuard":null,"tryCatchPattern":"try:\n    entries = browse(path)\nexcept HTTPError as e:\n    if e.response.status_code == 403 and 'Permission denied' in e.response.json()['detail']:\n        show_user('Grant the backend read access to the parent directory')\n    else: raise","preventionTips":["Keep model trees owned by (or readable by) the backend user.","Register the deepest readable directory as a scan folder so walks skip restricted parents.","Avoid nesting model data under directories with 700 perms belonging to other users."],"tags":["filesystem","permissions","browse","models","os-error"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}