unslothai/unsloth · error · ValueError
Linked folder changed after it was selected
Error message
Linked folder changed after it was selected
What it means
Raised inside create_folder's transaction when re-computed _root_identity(normalized) differs from the identity captured at function entry (root_device, root_inode), or from the caller-supplied expected_identity. This is a TOCTOU guard: between the user 'selecting' a folder and the row being inserted, the directory was replaced (new inode) or remounted (new device).
Source
Thrown at studio/backend/core/rag/folder_sync.py:268
"SELECT * FROM linked_folders WHERE scope=?", (scope,)
).fetchall()
for row in existing:
existing_key = _path_key(row["path"])
if existing_key == normalized_key or _same_file(row["path"], normalized):
if row["status"] == "retired" or row["delete_remove_index"] is not None:
raise ValueError("Linked folder is still being removed")
conn.rollback()
return _reauthorize_folder(row["id"], normalized, expected_identity)
if _paths_overlap(existing_key, normalized_key):
raise ValueError("Linked folders in the same scope cannot overlap")
try:
current_identity = _root_identity(normalized)
except RuntimeError as exc:
raise ValueError(str(exc)) from exc
if current_identity != (root_device, root_inode) or (
expected_identity is not None and current_identity != expected_identity
):
raise ValueError("Linked folder changed after it was selected")
conn.execute(
"INSERT INTO linked_folders(id, scope_type, scope_id, scope, path, name, "
"root_device, root_inode, auto_sync, status, created_at, updated_at) "
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?)",
(
folder_id,
scope_type,
scope_id,
scope,
normalized,
(name or Path(normalized).name or normalized).strip(),
*_store_identity((root_device, root_inode)),
int(auto_sync),
"pending",
now,
now,
),
)View on GitHub (pinned to 203007d190)
Solutions
- Retry create_folder without expected_identity (or with a freshly captured identity) after confirming the directory is the intended one.
- If the swap was intentional (deployment replaced the folder), capture the new st_dev/st_ino and pass it as expected_identity.
- Serialize concurrent creates for the same path with the scope lock / UI-level disabling of the button.
Example fix
# before expected = stat_dir(path) # captured long before create_folder(..., expected_identity=expected) # after expected = os.stat(path), then immediately: create_folder(..., expected_identity=(s.st_dev, s.st_ino)) # on ValueError 'changed after it was selected': re-stat and retry once
Defensive patterns
Strategy: try-catch
Validate before calling
# Capture identity immediately before the call to shrink the window: st = os.stat(path) expected = (st.st_dev, st.st_ino) create_folder(..., expected_identity=expected)
Try / catch
try:
folder = create_folder(..., expected_identity=expected)
except ValueError as e:
if "changed after it was selected" in str(e):
st = os.stat(path) # re-capture and retry once
folder = create_folder(..., expected_identity=(st.st_dev, st.st_ino))
else:
raise Prevention
- Capture expected_identity right before create_folder, not at page load.
- Disable the submit button while a create is in flight to avoid double submits.
- Do not run directory-swapping deploys while users are linking folders.
When it happens
Trigger: A swap: rm -rf dir && mv other dir between the pre-check and the INSERT; concurrent create_folder calls where one already re-authorized the row; the folder being on removable media that unmounted/remounted mid-call; expected_identity captured in the UI flow from a stale stat.
Common situations: Installer/updater scripts replacing directories atomically; two tabs linking the same folder simultaneously; USB/network drives with unstable device ids; a frontend sending an expected_identity captured before a file-system migration.
Related errors
- Linked folder root identity changed during scan
- Linked source is not a regular file
- Linked folder no longer resolves to its registered path
- The linked-folder scope no longer exists
- Linked folder is still being removed
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/1bb9af52d74867e3.
Report an issue: GitHub.