{"record":{"id":"90976943ecb7fbec","repo":"unslothai/unsloth","slug":"linked-folders-in-the-same-scope-cannot-overlap","errorCode":null,"errorMessage":"Linked folders in the same scope cannot overlap","messagePattern":"Linked folders in the same scope cannot overlap","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/rag/folder_sync.py","lineNumber":260,"sourceCode":"        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 (\n                expected_identity is not None and current_identity != expected_identity\n            ):\n                raise ValueError(\"Linked folder changed after it was selected\")\n            conn.execute(\n                \"INSERT INTO linked_folders(id, scope_type, scope_id, scope, path, name, \"\n                \"root_device, root_inode, auto_sync, status, created_at, updated_at) \"\n                \"VALUES(?,?,?,?,?,?,?,?,?,?,?,?)\",\n                (\n                    folder_id,\n                    scope_type,\n                    scope_id,\n                    scope,\n                    normalized,","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/rag/folder_sync.py#L242-L278","documentation":"create_folder rejects a path when _paths_overlap finds it is a parent/child (or samefile alias via different mount points/bind mounts) of any existing linked folder in the same scope. Overlapping roots would double-ingest files and make delete/retire bookkeeping ambiguous, so each scope's folders must form a forest of disjoint subtrees.","triggerScenarios":"Adding /home/user/docs when /home/user is already linked in the same KB; adding a subfolder of an existing link; adding a parent of an existing link; two different paths that os.path.samefile resolves to one inode (bind mounts, case-insensitive filesystems, 8.3 short names on Windows).","commonSituations":"Users trying to sync one small subfolder for 'faster' indexing while the parent is linked; Windows paths differing only by case or slash style; symlinks aliasing into an existing link (samefile detection).","solutions":["Link a sibling directory outside the existing folder's subtree, or use the existing parent link and rely on it for the subfolder.","Remove the overlapping existing folder first (remove_folder) and then register the narrower/wider path you actually want.","On Windows, normalize casing and separators before comparing so accidental 'overlap' from case-insensitivity is not created in the first place."],"exampleFix":"# before: /home/user already linked in this KB\ncreate_folder(scope_type=\"knowledge_base\", scope_id=sid, path=\"/home/user/docs\")\n\n# after: link a disjoint sibling\ncreate_folder(scope_type=\"knowledge_base\", scope_id=sid, path=\"/home/user-archive/docs\")","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef overlaps_existing(new_path: str, existing_paths: list[str]) -> bool:\n    a = Path(os.path.realpath(new_path))\n    for p in existing_paths:\n        b = Path(os.path.realpath(p))\n        if a == b or a in b.parents or b in a.parents:\n            return True\n    return False","typeGuard":null,"tryCatchPattern":"try:\n    create_folder(...)\nexcept ValueError as e:\n    if \"cannot overlap\" in str(e):\n        show_user(\"This folder is inside (or contains) an already linked folder in this scope.\")\n    else:\n        raise","preventionTips":["Fetch the scope's existing linked folders and check parent/child relations client-side before submit.","Link disjoint sibling directories rather than nested subtrees.","Normalize case and separators before comparing on Windows."],"tags":["rag","folder-sync","filesystem","validation","overlap"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}