{"record":{"id":"4421faf3ab9071a8","repo":"unslothai/unsloth","slug":"linked-folder-root-identity-changed","errorCode":null,"errorMessage":"Linked folder root identity changed","messagePattern":"Linked folder root identity changed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/rag/folder_sync.py","lineNumber":928,"sourceCode":"            yield row\n            previous = state\n            last_sent = time.monotonic()\n        elif time.monotonic() - last_sent >= _JOB_EVENT_KEEPALIVE_S:\n            yield None\n            last_sent = time.monotonic()\n        if row[\"status\"] in _TERMINAL:\n            return\n        time.sleep(0.5)\n\n\ndef _scan(\n    root: str, expected_identity: tuple[int, int] | None = None\n) -> tuple[dict[str, dict], tuple[int, int]]:\n    from hub.storage.scan_folders import contains_sensitive_path_component, is_denied_system_path\n\n    identity = _root_identity(root)\n    if expected_identity is not None and identity != expected_identity:\n        raise RuntimeError(\"Linked folder root identity changed\")\n\n    found: dict[str, dict] = {}\n    mount_points = _mount_points()\n    root_identities = frozenset({identity}) if identity[1] not in (None, 0) else frozenset()\n    pending = [(root, frozenset({_path_key(root)}), root_identities, 0)]\n    while pending:\n        directory, ancestor_paths, ancestor_identities, depth = pending.pop()\n        with os.scandir(directory) as entries:\n            for entry in entries:\n                full = entry.path\n                if entry.is_symlink():\n                    continue\n                if entry.is_dir(follow_symlinks = False):\n                    resolved = os.path.realpath(full)\n                    if (\n                        not _is_within(root, resolved)\n                        or contains_sensitive_path_component(os.path.relpath(resolved, root))\n                        or is_denied_system_path(resolved)","sourceCodeStart":910,"sourceCodeEnd":946,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/rag/folder_sync.py#L910-L946","documentation":"_scan() re-derives the folder's root identity and compares it to expected_identity (the st_dev/st_ino persisted in linked_folders). A mismatch means the physical directory at the registered path changed identity — replaced, moved, or remounted — so the scan aborts before walking files, preventing ingestion under a swapped root.","triggerScenarios":"A sync job calling _scan(root, expected_identity) after the folder was deleted and recreated (new inode), moved across filesystems, or the storage was remounted with a different device id (some network/overlay filesystems change st_dev per mount).","commonSituations":"Backup/restore tools that recreate directories; Docker overlay mounts with unstable device ids; NAS remounts; user 'refreshing' a folder by delete+recreate.","solutions":["Restore the original directory (same inode) or remove and re-register the linked folder so the stored identity matches the new one.","For mounts with unstable device ids, prefer a stable local path or a filesystem with persistent ids.","Surface this error to the user as 'folder changed, please re-link' rather than retrying."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import os, stat\n\ndef root_identity_matches(path: str, expected: tuple[int, int]) -> bool:\n    st = os.stat(path)\n    return (st.st_dev, st.st_ino) == expected","typeGuard":null,"tryCatchPattern":"try:\n    run_sync_job(folder_id)\nexcept RuntimeError as e:\n    if \"root identity changed\" in str(e):\n        mark_folder_needs_relink(folder_id)  # do NOT blind-retry\n    else:\n        raise","preventionTips":["Never delete-and-recreate a linked directory; update contents in place.","Prefer filesystems with stable device/inode ids for linked folders (avoid overlay/FUSE where ids churn).","Monitor sync job failures and prompt re-link on identity errors instead of retry loops."],"tags":["rag","folder-sync","filesystem","integrity","scan"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}