unslothai/unsloth · warning · ValueError

Linked folder changed while it was reauthorized

Error message

Linked folder changed while it was reauthorized

What it means

In _reauthorize_folder (reached from create_folder when the path matches an existing active row), after taking BEGIN IMMEDIATE the linked_folders row with that id no longer exists. Between the outer duplicate-detection read and this inner transaction, another thread removed/deleted the row, so re-authorization has nothing to update.

Source

Thrown at studio/backend/core/rag/folder_sync.py:309

        except Exception:
            conn.rollback()
            raise
        finally:
            conn.close()


def _reauthorize_folder(
    folder_id: str, path: str, expected_identity: tuple[int, int] | None
) -> dict:
    with _folder_lock(folder_id):
        conn = rag_db.get_connection()
        try:
            conn.execute("BEGIN IMMEDIATE")
            if (
                conn.execute("SELECT 1 FROM linked_folders WHERE id=?", (folder_id,)).fetchone()
                is None
            ):
                raise ValueError("Linked folder changed while it was reauthorized")
            try:
                identity = _root_identity(path)
            except RuntimeError as exc:
                raise ValueError(str(exc)) from exc
            if expected_identity is not None and identity != expected_identity:
                raise ValueError("Linked folder changed after it was selected")
            conn.execute(
                "UPDATE linked_folders SET root_device=?, root_inode=?, updated_at=? WHERE id=?",
                (*_store_identity(identity), _now(), folder_id),
            )
            conn.commit()
            return dict(
                conn.execute("SELECT * FROM linked_folders WHERE id=?", (folder_id,)).fetchone()
            )
        except Exception:
            conn.rollback()
            raise
        finally:

View on GitHub (pinned to 203007d190)

Solutions

  1. Retry create_folder: with the old row gone, it will now take the plain INSERT path.
  2. Catch the ValueError at the call site and treat it as 'retry once', not as a permanent failure.
  3. Avoid firing add and remove for the same path concurrently from the client.

Example fix

# before
folder = create_folder(...)

# after
for attempt in range(2):
    try:
        folder = create_folder(...)
        break
    except ValueError as e:
        if "reauthorized" not in str(e) or attempt == 1:
            raise
Defensive patterns

Strategy: retry

Try / catch

try:
    folder = create_folder(...)
except ValueError as e:
    if "changed while it was reauthorized" in str(e):
        folder = create_folder(...)  # row vanished; plain INSERT path now applies
    else:
        raise

Prevention

When it happens

Trigger: Concurrent create_folder and remove_folder for the same path/scope on different threads: outer transaction rolls back to call _reauthorize_folder, meanwhile the row is deleted (retire completes) before its BEGIN IMMEDIATE runs.

Common situations: Double-click / double-submit races between add and remove in the UI; a background reconciliation deleting stale rows while a user re-links the same folder.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/639f6feeeabaedef. Report an issue: GitHub.