{"record":{"id":"0e95285d51276c99","repo":"unslothai/unsloth","slug":"linked-folders-support-only-knowledge-base-and-pro-0e9528","errorCode":null,"errorMessage":"Linked folders support only knowledge-base and project scopes","messagePattern":"Linked folders support only knowledge-base and project scopes","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"studio/backend/routes/rag.py","lineNumber":380,"sourceCode":"        if get_chat_project(document[\"project_id\"]) is None:\n            raise HTTPException(status_code = 404, detail = \"Document not found\")\n\n\ndef _create_linked_folder(scope_type: str, scope_id: str, payload: LinkFolderRequest) -> dict:\n    path, signed_identity = _resolve_linked_folder_path(payload.native_path_lease)\n    try:\n        with folder_sync.scope_lock(_scope_for_owner(scope_type, scope_id)):\n            _require_scope_owner(scope_type, scope_id)\n            folder, job_id = folder_sync.create_folder_with_sync(\n                scope_type = scope_type,\n                scope_id = scope_id,\n                path = path,\n                expected_identity = signed_identity,\n                name = payload.name,\n                auto_sync = payload.auto_sync,\n            )\n    except ValueError as exc:\n        raise HTTPException(status_code = 400, detail = str(exc)) from exc\n    job = folder_sync.get_job(job_id)\n    return {\"linkedFolder\": _folder_view(folder), \"job\": _folder_job_view(job)}\n\n\n@router.get(\"/knowledge-bases\")\ndef list_knowledge_bases(subject: str = Depends(get_current_subject)) -> dict:\n    try:\n        conn = rag_db.get_connection()\n    except rag_db.RagExtensionUnavailable:\n        # RAG_AVAILABLE only covers the import; the native library can still fail to\n        # load per connection (a missing vec0 binary in the venv). The UI polls this\n        # list, so 500ing here costs a traceback every few seconds for a condition that\n        # never changes within a session. rag_db has warned once; an empty list is what\n        # a machine without RAG has anyway. The marker is what keeps that honest: it is\n        # the difference between \"no knowledge bases yet\" and \"RAG cannot run here\", and\n        # without it the empty page looks ready to use. Only the unavailable case\n        # degrades: a locked or corrupt database still raises.\n        return {\"knowledgeBases\": [], **_availability(False)}","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/rag.py#L362-L398","documentation":"Raised inside folder_sync.create_folder_with_sync (and the underlying create_folder) when scope_type is not in {'knowledge_base', 'project'}: ValueError('Linked folders support only knowledge-base and project scopes'). The route _create_linked_folder catches ValueError and maps it to HTTP 400. Linked folders can only hang off KBs and chat projects — global/user-level folder links are not supported.","triggerScenarios":"Calling the link-folder endpoint with scope_type something other than 'knowledge_base' or 'project' (e.g. 'user', 'workspace', 'global', or a typo like 'knowledge-base' with a hyphen).","commonSituations":"Client-side scope enum drifts from the backend's two allowed literals; a new UI surface tries to attach folders at a level the backend does not support; hyphen-vs-underscore confusion between the API's scope names and UI constants.","solutions":["Send scope_type exactly 'knowledge_base' or 'project' (underscore form).","Ensure the folder is linked through a concrete KB or project endpoint rather than a user/global one.","Keep the client's scope union type generated from / in sync with the backend's two literals."],"exampleFix":"// before\napi.linkFolder({ scope_type: 'knowledge-base', ... }) // hyphen -> 400\n// after\napi.linkFolder({ scope_type: 'knowledge_base', ... })","handlingStrategy":"type-guard","validationCode":"const SCOPES = ['knowledge_base', 'project'] as const;\nif (!SCOPES.includes(scopeType)) throw new Error(`scope must be one of ${SCOPES.join(', ')}`);","typeGuard":"type LinkScope = 'knowledge_base' | 'project';\nconst isLinkScope = (s: string): s is LinkScope =>\n  s === 'knowledge_base' || s === 'project';","tryCatchPattern":null,"preventionTips":["Type the client's scope field as the literal union; compile-time drift then cannot reach the API.","Use underscores, never hyphens, in scope names.","Route folder-linking only through KB/project endpoints."],"tags":["http-400","linked-folder","scope-validation","rag","studio-backend"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}