unslothai/unsloth · error · RuntimeError
Linked folder root identity changed
Error message
Linked folder root identity changed
What it means
_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.
Source
Thrown at studio/backend/core/rag/folder_sync.py:928
yield row
previous = state
last_sent = time.monotonic()
elif time.monotonic() - last_sent >= _JOB_EVENT_KEEPALIVE_S:
yield None
last_sent = time.monotonic()
if row["status"] in _TERMINAL:
return
time.sleep(0.5)
def _scan(
root: str, expected_identity: tuple[int, int] | None = None
) -> tuple[dict[str, dict], tuple[int, int]]:
from hub.storage.scan_folders import contains_sensitive_path_component, is_denied_system_path
identity = _root_identity(root)
if expected_identity is not None and identity != expected_identity:
raise RuntimeError("Linked folder root identity changed")
found: dict[str, dict] = {}
mount_points = _mount_points()
root_identities = frozenset({identity}) if identity[1] not in (None, 0) else frozenset()
pending = [(root, frozenset({_path_key(root)}), root_identities, 0)]
while pending:
directory, ancestor_paths, ancestor_identities, depth = pending.pop()
with os.scandir(directory) as entries:
for entry in entries:
full = entry.path
if entry.is_symlink():
continue
if entry.is_dir(follow_symlinks = False):
resolved = os.path.realpath(full)
if (
not _is_within(root, resolved)
or contains_sensitive_path_component(os.path.relpath(resolved, root))
or is_denied_system_path(resolved)View on GitHub (pinned to 203007d190)
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.
Defensive patterns
Strategy: validation
Validate before calling
import os, stat
def root_identity_matches(path: str, expected: tuple[int, int]) -> bool:
st = os.stat(path)
return (st.st_dev, st.st_ino) == expected Try / catch
try:
run_sync_job(folder_id)
except RuntimeError as e:
if "root identity changed" in str(e):
mark_folder_needs_relink(folder_id) # do NOT blind-retry
else:
raise Prevention
- 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.
When it happens
Trigger: 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).
Common situations: Backup/restore tools that recreate directories; Docker overlay mounts with unstable device ids; NAS remounts; user 'refreshing' a folder by delete+recreate.
Related errors
- Linked folder no longer resolves to its registered path
- Linked folders in the same scope cannot overlap
- Linked folder changed after it was selected
- Folder nesting exceeds the {_MAX_FOLDER_DEPTH}-level scan li
- Folder contains more than the {config.FOLDER_MAX_FILES} supp
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/4421faf3ab9071a8.
Report an issue: GitHub.