unslothai/unsloth · error · NativePathLeaseError

Native path is no longer a regular file.

Error message

Native path is no longer a regular file.

What it means

lstat() shows the signed path is now a symlink. The lease scheme requires the canonical path itself to be a regular file (or directory), not a link, because symlinks can be swapped after signing to redirect the backend's read to a different target (a TOCTOU-style bypass of the path grant).

Source

Thrown at studio/backend/utils/native_path_leases.py:192

        secret,
        payload_b64.encode("ascii"),
        hashlib.sha256,
    ).digest()
    supplied_signature = _b64decode(signature_b64)
    if not hmac.compare_digest(expected_signature, supplied_signature):
        raise NativePathLeaseError("Native path grant signature is invalid.")

    payload = _decode_payload(payload_b64)
    _validate_payload(payload, operation = operation, expected_kind = expected_kind)

    path = Path(str(payload["canonical_path"]))
    _reject_network_or_device_path(path)
    try:
        signed_lstat = os.lstat(path)
    except OSError as exc:
        raise NativePathLeaseError("Native path is no longer accessible.") from exc
    if _stat_module.S_ISLNK(signed_lstat.st_mode):
        raise NativePathLeaseError("Native path is no longer a regular file.")
    try:
        resolved = path.resolve(strict = True)
    except OSError as exc:
        raise NativePathLeaseError("Native path is no longer accessible.") from exc
    _reject_network_or_device_path(resolved)
    if not _same_native_path(resolved, path):
        raise NativePathLeaseError("Native path grant no longer resolves to the selected path.")

    identity_options = _identity_options(payload)
    grant = NativePathGrant(
        operation = str(payload["operation"]),
        canonical_path = resolved,
        path_kind = str(payload["path_kind"]),
        path_type = str(payload["path_type"]),
        source_kind = str(payload["source_kind"]),
        token_id_hash = str(payload["token_id_hash"]),
        display_label = str(payload.get("display_label") or resolved.name),
        expires_at_ms = _required_int(payload, "expires_at_ms"),

View on GitHub (pinned to 203007d190)

Solutions

  1. Re-select the target file so the grant is issued against the current, real file.
  2. If you control the signing side (Rust shell), ensure it signs the resolved canonical path, not a symlink path.
  3. Reject user selections that are symlinks at pick time so a grant is never issued for one.
  4. Do not attempt to work around this check — it is a deliberate security guard against post-signing redirection.
Defensive patterns

Strategy: try-catch

Validate before calling

import os, stat

def is_plain_file(path_str: str) -> bool:
    try:
        return not stat.S_ISLNK(os.lstat(path_str).st_mode)
    except OSError:
        return False

Try / catch

try:
    grant = verify_native_path_lease(lease, operation=OP)
except NativePathLeaseError as exc:
    if "no longer a regular file" in str(exc):
        return error_response(409, "The selected item changed on disk. Re-select it.")
    raise

Prevention

When it happens

Trigger: The user (or a script) replaced the originally selected regular file with a symlink between grant issuance and verification; the path was always a symlink but was canonicalized at signing while the link was later recreated pointing elsewhere; or the selection flow signed a non-canonical path on a platform where lstat and resolve disagree.

Common situations: Files managed by sync tools (Dropbox/ iCloud placeholder replacement), user reorganizing with ln -s, build pipelines that swap artifact files with symlink indirection, or attempts to make a signed grant point at /etc/shadow via a symlink planted at the original location.

Related errors


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