unslothai/unsloth · error · RuntimeError

Linked folder no longer resolves to its registered path

Error message

Linked folder no longer resolves to its registered path

What it means

Thrown by _root_identity() when the registered linked folder path resolves through a symlink or other indirection at scan/sync time: realpath(root) no longer equals the normalized stored path. The module enforces that a linked folder root stays a real directory that resolves exactly to the path registered in the linked_folders table, so a root swapped to a symlink (or mounted over) is treated as a security/integrity failure rather than silently synced.

Source

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

            raise ValueError("The entire home folder cannot be registered")
    except RuntimeError:
        pass
    if contains_sensitive_path_component(normalized):
        raise ValueError("Credential or configuration directories are not allowed")
    if is_denied_system_path(normalized):
        raise ValueError("System directories are not allowed")
    return normalized


def _root_identity(root: str) -> tuple[int, int]:
    try:
        root_stat = os.lstat(root)
    except OSError as exc:
        raise RuntimeError("Linked folder is unavailable") from exc
    if stat.S_ISLNK(root_stat.st_mode) or not stat.S_ISDIR(root_stat.st_mode):
        raise RuntimeError("Linked folder is no longer a regular directory")
    if os.path.normcase(os.path.realpath(root)) != os.path.normcase(root):
        raise RuntimeError("Linked folder no longer resolves to its registered path")
    return root_stat.st_dev, root_stat.st_ino


def _store_identity(identity: tuple[int, int]) -> tuple[int | str, int | str]:
    return tuple(value if value <= _SQLITE_INTEGER_MAX else f"x{value:x}" for value in identity)


def _file_identity(metadata: dict) -> tuple[int | str, int | str]:
    return _store_identity((metadata["device"], metadata["inode"]))


def _load_identity(device_id: int | str, file_id: int | str) -> tuple[int, int]:
    def load(value: int | str) -> int:
        return (
            int(value[1:], 16) if isinstance(value, str) and value.startswith("x") else int(value)
        )

    return load(device_id), load(file_id)

View on GitHub (pinned to 203007d190)

Solutions

  1. Replace the symlink with a real directory (or move the data back so the registered path is a real directory), then re-run sync.
  2. If the data moved, remove the linked folder and register the new concrete path via create_folder.
  3. Re-register the folder using its fully resolved real path (realpath output) so realpath(root) == root holds.
  4. Check os.path.realpath and os.path.islink on the stored path before each sync and surface a re-authorization prompt to the user.

Example fix

# before
ln -s /mnt/newdata /home/user/linked_data  # registered path now a symlink

# after
rm /home/user/linked_data && mv /mnt/newdata /home/user/linked_data  # real directory again
Defensive patterns

Strategy: validation

Validate before calling

import os, stat

def root_resolves_to_registered(path: str) -> bool:
    st = os.lstat(path)
    return not stat.S_ISLNK(st.st_mode) and stat.S_ISDIR(st.st_mode) and \
        os.path.normcase(os.path.realpath(path)) == os.path.normcase(path)

Try / catch

try:
    sync_folder(...)
except RuntimeError as e:
    if "no longer resolves" in str(e):
        mark_folder_needs_relink(folder_id)  # prompt user to re-register
    else:
        raise

Prevention

When it happens

Trigger: Any sync job, scan (_scan), or create_folder/_reauthorize_folder call that invokes _root_identity on a stored path where realpath() differs: an administrator replaced the directory with a symlink, a bind-mount/symlink farm was introduced after registration, or the folder was registered before symlink rules existed and realpath now canonicalizes differently (e.g. /tmp -> /private/tmp on macOS).

Common situations: macOS /tmp vs /private/tmp case sensitivity mismatch, Docker volumes mounted as symlinks, users 'reorganizing' data by symlinking the old directory name, network shares whose realpath changes after remount.

Related errors


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