{"record":{"id":"9f84ecf4a135383b","repo":"unslothai/unsloth","slug":"not-a-directory-os-path-basename-str-current","errorCode":null,"errorMessage":"Not a directory: {os.path.basename(str(current))}","messagePattern":"Not a directory: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"studio/backend/routes/models.py","lineNumber":1732,"sourceCode":"                raise HTTPException(\n                    status_code = 403,\n                    detail = \"System directories are not browseable.\",\n                )\n            current = resolved_child\n\n        if contains_sensitive_path_component(str(current)):\n            raise HTTPException(\n                status_code = 403,\n                detail = \"Credential or configuration directories are not browseable.\",\n            )\n        # Zero-component case: the requested path IS an allowlist root (legacy \"/\" or a drive root).\n        if is_denied_system_path(str(current)):\n            raise HTTPException(\n                status_code = 403,\n                detail = \"System directories are not browseable.\",\n            )\n        if not current.is_dir():\n            raise HTTPException(\n                status_code = 400,\n                detail = f\"Not a directory: {os.path.basename(str(current))}\",\n            )\n        return current\n\n    raise HTTPException(\n        status_code = 403,\n        detail = (\n            \"Path is not in the browseable allowlist. Register it via \"\n            \"POST /api/models/scan-folders first, or pick a directory \"\n            \"under your home folder.\"\n        ),\n    )\n\n\n# Sync (def, not async) so FastAPI runs the blocking filesystem I/O in the threadpool: a\n# disconnected mapped drive can make the probe wait out its timeout, which on the event\n# loop would stall every other request. Matches the hub browse endpoint.","sourceCodeStart":1714,"sourceCodeEnd":1750,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/models.py#L1714-L1750","documentation":"Raised as a 400 by _resolve_browse_target when the fully resolved target exists, passed the allowlist/sensitive/system checks, but current.is_dir() is False — the path points at a regular file (or a non-directory entry). The browse endpoint lists directory contents, so a file target is a client error, not a server fault.","triggerScenarios":"GET browse-folders?path=/home/user/models/model.safetensors — walking succeeds to the file, every security check passes, and the final is_dir() guard rejects it.","commonSituations":"Folder picker fed a file path (drag-drop of a model file, remembered selection, path input autocomplete); front-end confusing a file entry with a directory in its tree model.","solutions":["Pass the containing directory instead of the file: strip the last path segment before calling browse-folders.","In the UI, only make directories navigable — disable browse for file entries.","If you intended to select a model file, use the local-models listing endpoint rather than the folder browser."],"exampleFix":"// before\nfetch(`/api/models/browse-folders?path=${selectedEntry.path}`); // selectedEntry is a file -> 400\n\n// after\nif (selectedEntry.isDir) {\n  fetch(`/api/models/browse-folders?path=${selectedEntry.parentPath ?? selectedEntry.path}`);\n}","handlingStrategy":"type-guard","validationCode":"import os\n\nif not os.path.isdir(os.path.realpath(browse_path)):\n    browse_path = os.path.dirname(browse_path.rstrip('/')) or home_dir()\n# now safe to call browse-folders","typeGuard":"function isBrowsableDir(entry: {path: string; isDir?: boolean}): boolean {\n  return entry.isDir === true && !entry.path.endsWith('.safetensors');\n}","tryCatchPattern":"try {\n  entries = await browse(path);\n} catch (e) {\n  if (e.status === 400 && /Not a directory/.test(e.detail)) {\n    entries = await browse(parentOf(path));\n  } else throw e;\n}","preventionTips":["Only make directories navigable in the picker UI.","Strip the last segment when a file entry is selected for browsing.","Use the local-models endpoint, not browse-folders, to target individual model files."],"tags":["filesystem","validation","browse","client-error"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}