unslothai/unsloth · error · NativePathLeaseError

Native path grant issue time is invalid.

Error message

Native path grant issue time is invalid.

What it means

The grant's issued_at_ms is more than 30 seconds in the future relative to the backend clock, which the backend treats as an invalid issue time. This 30-second window is a deliberately small allowed clock-skew tolerance; anything beyond it suggests clock drift, a replay of a grant minted elsewhere, or a fabricated payload. The backend rejects future-dated grants to prevent extending a lease's effective lifetime via a fast clock.

Source

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

    )
    missing = [key for key in required if key not in payload]
    if missing:
        raise NativePathLeaseError("Native path grant payload is missing required fields.")
    if _required_int(payload, "version") != 1:
        raise NativePathLeaseError("Native path grant version is unsupported.")
    if payload["operation"] != operation:
        raise NativePathLeaseError("Native path grant operation is invalid.")
    if expected_kind and payload["path_kind"] != expected_kind:
        raise NativePathLeaseError("Native path grant kind is invalid.")
    now_ms = int(time.time() * 1000)
    issued_at_ms = _required_int(payload, "issued_at_ms")
    expires_at_ms = _required_int(payload, "expires_at_ms")
    if issued_at_ms >= expires_at_ms:
        raise NativePathLeaseError("Native path grant timestamps are inconsistent.")
    if expires_at_ms <= now_ms:
        raise NativePathLeaseError("Native path grant has expired.")
    if issued_at_ms > now_ms + 30_000:
        raise NativePathLeaseError("Native path grant issue time is invalid.")
    for key in ("canonical_path", "nonce", "token_id_hash", "display_label"):
        raw = payload.get(key)
        if raw is None:
            continue
        if "\x00" in str(raw):
            raise NativePathLeaseError("Native path grant contains invalid characters.")


def _validate_current_stat(
    grant: NativePathGrant, identity_options: tuple[tuple[int, int], ...]
) -> tuple[int, int] | None:
    try:
        st = os.lstat(grant.canonical_path)
    except OSError as exc:
        raise NativePathLeaseError("Native path is no longer accessible.") from exc
    if _stat_module.S_ISLNK(st.st_mode):
        raise NativePathLeaseError("Native path is no longer a regular file.")
    if grant.path_type == "file":

View on GitHub (pinned to 203007d190)

Solutions

  1. Measure skew: compare date +%s%3N in the Tauri shell (or host) vs the backend process environment.
  2. Resync clocks (enable NTP, restart the VM/WSL guest, or fix RTC to UTC in dual-boot setups), then request a fresh grant.
  3. If skew is structural (e.g. sandboxed backend), ensure both signer and verifier derive time from the same host clock.
  4. Regenerate the grant after the clock is fixed; the existing one stays rejected until it falls inside the 30s window (i.e. effectively re-issue).

Example fix

# before: diagnose
# host clock 14:02, backend (WSL) clock 14:05 -> 3min skew, grant issued_at is 'future'

# after: resync and re-issue
sudo hwclock -s            # or restart WSL: wsl --shutdown
wsl --shutdown && wsl      # guest re-reads host clock
# then re-pick the file to mint a fresh grant
Defensive patterns

Strategy: retry

Validate before calling

import base64, json, time

def issue_time_plausible(lease: str, tolerance_ms: int = 30_000) -> bool:
    payload = json.loads(base64.urlsafe_b64decode(lease.split('.')[0] + '=='))
    return int(payload['issued_at_ms']) <= int(time.time() * 1000) + tolerance_ms

Try / catch

try:
    grant = verify_native_path_lease(lease, operation='read')
except NativePathLeaseError as exc:
    if 'issue time is invalid' in str(exc):
        raise RuntimeError('Clock skew detected between signer and backend; sync clocks and retry') from exc
    raise

Prevention

When it happens

Trigger: verify_native_path_lease() with issued_at_ms > now_ms + 30_000. Happens when the machine/process that signed the grant runs more than 30s ahead (manual clock set, VM resume, dual-boot RTC state), or when a grant string is reused from an environment with a different clock.

Common situations: Windows/Linux dual-boot leaving the RTC in local vs UTC mode (~hours of skew); a VM or WSL guest whose clock drifted after host sleep; NTP not yet converged on a freshly booted machine; testing with a grant fixture generated on another machine.

Related errors


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