unslothai/unsloth · error · HTTPException

Linked folders support only knowledge-base and project scope

Error message

Linked folders support only knowledge-base and project scopes

What it means

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.

Source

Thrown at studio/backend/routes/rag.py:380

        if get_chat_project(document["project_id"]) is None:
            raise HTTPException(status_code = 404, detail = "Document not found")


def _create_linked_folder(scope_type: str, scope_id: str, payload: LinkFolderRequest) -> dict:
    path, signed_identity = _resolve_linked_folder_path(payload.native_path_lease)
    try:
        with folder_sync.scope_lock(_scope_for_owner(scope_type, scope_id)):
            _require_scope_owner(scope_type, scope_id)
            folder, job_id = folder_sync.create_folder_with_sync(
                scope_type = scope_type,
                scope_id = scope_id,
                path = path,
                expected_identity = signed_identity,
                name = payload.name,
                auto_sync = payload.auto_sync,
            )
    except ValueError as exc:
        raise HTTPException(status_code = 400, detail = str(exc)) from exc
    job = folder_sync.get_job(job_id)
    return {"linkedFolder": _folder_view(folder), "job": _folder_job_view(job)}


@router.get("/knowledge-bases")
def list_knowledge_bases(subject: str = Depends(get_current_subject)) -> dict:
    try:
        conn = rag_db.get_connection()
    except rag_db.RagExtensionUnavailable:
        # RAG_AVAILABLE only covers the import; the native library can still fail to
        # load per connection (a missing vec0 binary in the venv). The UI polls this
        # list, so 500ing here costs a traceback every few seconds for a condition that
        # never changes within a session. rag_db has warned once; an empty list is what
        # a machine without RAG has anyway. The marker is what keeps that honest: it is
        # the difference between "no knowledge bases yet" and "RAG cannot run here", and
        # without it the empty page looks ready to use. Only the unavailable case
        # degrades: a locked or corrupt database still raises.
        return {"knowledgeBases": [], **_availability(False)}

View on GitHub (pinned to 203007d190)

Solutions

  1. Send scope_type exactly 'knowledge_base' or 'project' (underscore form).
  2. Ensure the folder is linked through a concrete KB or project endpoint rather than a user/global one.
  3. Keep the client's scope union type generated from / in sync with the backend's two literals.

Example fix

// before
api.linkFolder({ scope_type: 'knowledge-base', ... }) // hyphen -> 400
// after
api.linkFolder({ scope_type: 'knowledge_base', ... })
Defensive patterns

Strategy: type-guard

Validate before calling

const SCOPES = ['knowledge_base', 'project'] as const;
if (!SCOPES.includes(scopeType)) throw new Error(`scope must be one of ${SCOPES.join(', ')}`);

Type guard

type LinkScope = 'knowledge_base' | 'project';
const isLinkScope = (s: string): s is LinkScope =>
  s === 'knowledge_base' || s === 'project';

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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