{"record":{"id":"7e88d752386ab40c","repo":"unslothai/unsloth","slug":"permission-denied-reading-os-path-basename-str-ta","errorCode":null,"errorMessage":"Permission denied reading {os.path.basename(str(target))}","messagePattern":"Permission denied reading (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"studio/backend/routes/models.py","lineNumber":1815,"sourceCode":"    try:\n        target = _resolve_browse_target(path, allowed_roots)\n    except HTTPException:\n        requested_path = _normalize_browse_request_path(path)\n        if path is not None and path.strip():\n            logger.warning(\n                \"browse-folders: rejected path %r (normalized=%s)\",\n                path,\n                requested_path,\n            )\n        raise\n\n    entries: list[BrowseEntry] = []\n    truncated = False\n    visited = 0\n    try:\n        it = target.iterdir()\n    except PermissionError:\n        raise HTTPException(\n            status_code = 403,\n            detail = f\"Permission denied reading {os.path.basename(str(target))}\",\n        )\n    except OSError as exc:\n        logger.warning(\"browse-folders: could not read %s: %s\", target, exc, exc_info = True)\n        raise HTTPException(\n            status_code = 500,\n            detail = f\"Could not read {os.path.basename(str(target))}\",\n        )\n\n    try:\n        for child in it:\n            # Bound by *visited*, not *appended*: a cap on len(entries) would never trigger in dirs\n            # full of files. Counting visits caps worst-case work at ``_BROWSE_ENTRY_CAP``.\n            visited += 1\n            if visited > _BROWSE_ENTRY_CAP:\n                truncated = True\n                break","sourceCodeStart":1797,"sourceCodeEnd":1833,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/models.py#L1797-L1833","documentation":"Raised as a 403 by the browse-folders listing handler when target.iterdir() throws PermissionError on the final, already-validated target directory (unlike errors 1104/1105, which occur during the walk to the target). The backend can see the directory exists and is allowlisted, but the process lacks read permission to enumerate its entries.","triggerScenarios":"GET browse-folders?path=<allowed-dir> where the directory mode/ACL denies read to the backend user; directory owned by root with 700 while studio runs unprivileged.","commonSituations":"Models directory created by root or a container and not chowned; chmod 600 applied to a directory by mistake; Windows ACLs from a copied folder denying list access.","solutions":["Grant read+execute on the directory to the backend user: chmod a+rx /path/to/dir or set the ACL accordingly.","chown the directory to the user running the studio backend.","If intentional restriction, browse a different, readable directory."],"exampleFix":"# backend runs as 'beagle', dir owned by root mode 700\n# before\nGET /api/models/browse-folders?path=/data/models  # 403\n\n# after (root shell)\n# chown -R beagle:beagle /data/models\nGET /api/models/browse-folders?path=/data/models","handlingStrategy":"validation","validationCode":"import os\n\ndef listable(d: str) -> bool:\n    try:\n        it = os.scandir(d); next(iter(it), None); return True\n    except PermissionError:\n        return False\n    except OSError:\n        return False\n\nif not listable(target_dir):\n    raise PermissionError(f'backend lacks read access to {target_dir}')","typeGuard":null,"tryCatchPattern":"try:\n    entries = browse(dir)\nexcept HTTPError as e:\n    if e.response.status_code == 403 and 'Permission denied' in e.response.json()['detail']:\n        show_user('The backend process cannot read this folder — fix ownership/mode and retry.')\n    else: raise","preventionTips":["After creating model directories as root or in containers, chown them to the backend user.","Use chmod a+rx on directories meant to be browsable.","Verify with `sudo -u <backend-user> ls <dir>` before wiring the folder into the UI."],"tags":["filesystem","permissions","browse","models"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}