astrid-runtime/astrid · error
FSKit lease is expired
Error message
FSKit lease is expired
What it means
validate_lease compares the lease's expires_at_epoch_secs against the current system time and rejects leases that have already expired. Leases are short-lived credentials for FSKit mounts, so an expired lease is not accepted for launch.
Source
Thrown at crates/astrid-storage-provider-fskit/src/service.rs:151
{
bail!("FSKit service mountpoint overlaps the lease resource");
}
crate::validate_mountpoint_ancestors(&launch.mountpoint)?;
crate::validate_unmounted_mountpoint(&launch.mountpoint)?;
validate_control_path(&launch.control_path, &launch.lease.resource_path)?;
Ok(())
}
fn validate_lease(lease: &astrid_core::storage_filesystem::StorageMountLeaseV1) -> Result<()> {
if lease.lease_token.len() < 16 || lease.lease_token.len() > 4096 {
bail!("FSKit lease callback token is invalid");
}
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.context("read system clock")?
.as_secs();
if lease.expires_at_epoch_secs < now {
bail!("FSKit lease is expired");
}
if !lease.resource_path.is_absolute() || !lease.callback_path.is_absolute() {
bail!("FSKit lease paths must be absolute");
}
#[cfg(target_os = "macos")]
astrid_core::fskit_socket::validate_callback_path(lease.mount_id, &lease.callback_path)
.map_err(anyhow::Error::msg)?;
#[cfg(not(target_os = "macos"))]
if lease.callback_path != lease.resource_path.join("control.sock") {
bail!("FSKit callback path is not the kernel lease endpoint");
}
platform_fs::validate_private_directory(&lease.resource_path)
.context("validate private FSKit lease resource")?;
platform_fs::verify_no_redirects(&lease.resource_path)
.context("reject redirected FSKit lease resource")?;
platform_fs::validate_private_file(&lease.resource_path.join("lease.json"))
.context("validate private FSKit lease manifest")?;
let manifest = std::fs::read(lease.resource_path.join("lease.json"))View on GitHub (pinned to affd8760f4)
Solutions
- Request a fresh lease from the kernel/provider and relaunch with it
- Fix system clock synchronization (NTP) if clock skew caused the false expiry
- Stop caching lease files across runs; read a newly issued lease each launch
Example fix
// before
let lease = std::fs::read("stale-lease.json")?; // expired
// after
let lease = request_fresh_lease()?; // expires_at_epoch_secs > now Defensive patterns
Strategy: validation
Validate before calling
fn lease_live(lease: &StorageMountLeaseV1) -> bool {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
lease.expires_at_epoch_secs >= now
} Try / catch
match provider.run(launch) {
Err(e) if e.to_string().contains("lease is expired") => {
let launch = refresh_lease(launch)?;
provider.run(launch).await
}
r => r,
} Prevention
- Refresh leases shortly before launch; never cache across runs
- Keep NTP active to avoid clock-skew false expiries
- Add expiry checks in test fixtures that replay saved leases
When it happens
Trigger: validate_lease is called (via validate_launch or live_managed_callback_lease_is_accepted) with lease.expires_at_epoch_secs < now, e.g. a cached/replayed lease or a system clock set far in the future.
Common situations: Reusing a saved lease file after it expired; slow test runs replaying stale fixtures; machine clock skew (NTP drift or incorrect system clock making 'now' appear past expiry).
Related errors
- FUSE lease is expired
- WinFsp lease is expired
- FSKit lease callback token is invalid
- FSKit lease paths must be absolute
- FSKit callback path is not the kernel lease endpoint
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/fc8ce1ab07ef4e04.
Report an issue: GitHub.