{"record":{"id":"042e0e768d028f5e","repo":"unslothai/unsloth","slug":"the-linked-folder-scope-no-longer-exists","errorCode":null,"errorMessage":"The linked-folder scope no longer exists","messagePattern":"The linked-folder scope no longer exists","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/rag/folder_sync.py","lineNumber":247,"sourceCode":"    except RuntimeError as exc:\n        raise ValueError(str(exc)) from exc\n    if expected_identity is not None and (root_device, root_inode) != expected_identity:\n        raise ValueError(\"Linked folder changed after it was selected\")\n    scope = (\n        store.kb_scope(scope_id)\n        if scope_type == \"knowledge_base\"\n        else store.project_scope(scope_id)\n    )\n    folder_id = str(uuid.uuid4())\n    now = _now()\n    with _scope_lock(scope):\n        conn = rag_db.get_connection()\n        try:\n            conn.execute(\"BEGIN IMMEDIATE\")\n            if conn.execute(\n                \"SELECT 1 FROM linked_folder_retired_scopes WHERE scope=?\", (scope,)\n            ).fetchone():\n                raise ValueError(\"The linked-folder scope no longer exists\")\n            normalized_key = _path_key(normalized)\n            existing = conn.execute(\n                \"SELECT * FROM linked_folders WHERE scope=?\", (scope,)\n            ).fetchall()\n            for row in existing:\n                existing_key = _path_key(row[\"path\"])\n                if existing_key == normalized_key or _same_file(row[\"path\"], normalized):\n                    if row[\"status\"] == \"retired\" or row[\"delete_remove_index\"] is not None:\n                        raise ValueError(\"Linked folder is still being removed\")\n                    conn.rollback()\n                    return _reauthorize_folder(row[\"id\"], normalized, expected_identity)\n                if _paths_overlap(existing_key, normalized_key):\n                    raise ValueError(\"Linked folders in the same scope cannot overlap\")\n            try:\n                current_identity = _root_identity(normalized)\n            except RuntimeError as exc:\n                raise ValueError(str(exc)) from exc\n            if current_identity != (root_device, root_inode) or (","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/rag/folder_sync.py#L229-L265","documentation":"Raised inside create_folder's BEGIN IMMEDIATE transaction when the target scope appears in the linked_folder_retired_scopes table. That tombstone table records scopes (knowledge bases/projects) that were deleted; new linked folders may not be attached to a deleted scope, keeping referential integrity without FK enforcement across stores.","triggerScenarios":"create_folder for a knowledge_base or project whose deletion ran concurrently or earlier and wrote a retirement row: a race between 'create KB -> add folder' and 'delete KB' on different threads, or a retry of an old request after the user deleted the KB/project in the UI.","commonSituations":"UI optimistic add racing a delete; queued background job re-registering a folder for a scope the user already removed; stale client tab submitting after project deletion.","solutions":["Have the caller verify the knowledge base/project still exists (store.kb_scope/store.project_scope) and refresh UI state before retrying.","Discard the request: the scope is deleted, linking folders to it is invalid by design.","If the scope was recreated with the same id, clear the retired-scopes tombstone as part of scope re-creation logic (or recreate with a new id)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Best-effort pre-check; the authoritative check is the tombstone table itself.\ndef scope_is_live(scope_type: str, scope_id: str) -> bool:\n    try:\n        (store.kb_scope(scope_id) if scope_type == \"knowledge_base\"\n         else store.project_scope(scope_id))\n        return True\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    create_folder(...)\nexcept ValueError as e:\n    if \"scope no longer exists\" in str(e):\n        refresh_ui_scope_state(scope_id)  # scope was deleted; drop the request\n    else:\n        raise","preventionTips":["Disable add-folder UI actions once a scope delete is issued.","Handle scope deletion and folder creation through one serialized queue per scope.","Treat this error as terminal (410 Gone), not retryable."],"tags":["rag","folder-sync","lifecycle","race-condition","validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}