astrid-runtime/astrid · error
WinFsp lease is expired
Error message
WinFsp lease is expired
What it means
Each mount lease carries an absolute expiry (expires_at_epoch_secs, Unix seconds). validate_service_launch compares it to the current system clock and aborts the mount if the lease has already expired. This enforces that only time-valid leases can bring up a WinFsp filesystem, preventing stale mounts from being resurrected.
Source
Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:263
|| launch.parent.token.chars().any(char::is_control)
{
bail!("WinFsp service parent token is invalid");
}
if let Some(identity) = launch.parent.start_identity.as_deref()
&& (identity.is_empty() || identity.len() > 512 || identity.chars().any(char::is_control))
{
bail!("WinFsp service parent start identity is invalid");
}
if launch.parent.start_identity.is_none() {
bail!("WinFsp service parent start identity is required on Windows");
}
let lease = &launch.lease;
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.context("read system clock")?
.as_secs();
if lease.expires_at_epoch_secs < now {
bail!("WinFsp lease is expired");
}
if lease.lease_token.len() < 16 || lease.lease_token.len() > 4096 {
bail!("WinFsp lease callback token is invalid");
}
if !lease.resource_path.is_absolute()
|| !lease.callback_path.is_absolute()
|| lease.callback_path != lease.resource_path.join("control.endpoint")
{
bail!("WinFsp lease paths are malformed");
}
platform_fs::validate_private_directory(&lease.resource_path)
.context("validate private WinFsp lease resource")?;
platform_fs::verify_no_redirects(&lease.resource_path)
.context("reject redirected WinFsp lease resource")?;
let manifest_path = lease.resource_path.join("lease.json");
platform_fs::validate_private_file(&manifest_path)
.context("validate private WinFsp lease manifest")?;
let manifest = std::fs::read(&manifest_path).context("read WinFsp lease manifest")?;View on GitHub (pinned to affd8760f4)
Solutions
- Obtain a fresh lease (re-run the mount request through the provider) so expires_at_epoch_secs is in the future, instead of replaying an old launch descriptor.
- Check the system clock on the service host (w32tm /query /status; re-sync with time.windows.com) — a forward clock skew alone produces this error with a valid lease.
- Re-mint the launch file right before starting the service; avoid persisting launch descriptors across restarts or long waits.
- If leases expire during legitimate startup delays, increase the lease TTL in the code that issues StorageMountLeaseV1.
Defensive patterns
Strategy: validation
Validate before calling
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_secs();
if lease.expires_at_epoch_secs <= now {
return Err(anyhow!("lease expired at {} (now {}): re-issue the lease", lease.expires_at_epoch_secs, now));
} Try / catch
match validate_launch(&launch) {
Err(e) if e.to_string().contains("lease is expired") => reissue_lease_and_retry(),
Err(e) => return Err(e),
Ok(()) => start_service(&launch),
} Prevention
- Always mint a fresh lease immediately before service start; never replay saved launch files
- Monitor system clock sync (NTP) on hosts running the service
- Set lease TTLs comfortably larger than worst-case startup/queue delays
- Treat this error as retryable-after-reissue, not retryable-as-is
When it happens
Trigger: service_main -> validate_service_launch where lease.expires_at_epoch_secs < SystemTime::now() duration since UNIX_EPOCH in seconds: the lease file (lease.json) was created earlier and its validity window has passed before/at service start.
Common situations: Resuming a session or replaying a saved launch descriptor hours later; a machine with a wrong system clock (skewed forward, or timezone/clock jumps after resume from sleep or VM snapshot) makes a fresh lease look expired; long CI queues where the lease was minted at queue time but consumed late.
Related errors
- FSKit lease is expired
- FUSE lease is expired
- WinFsp lease callback token is invalid
- WinFsp lease manifest exceeds the bounded size
- WinFsp launch lease does not match the kernel manifest
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/52a5702b5dbbb5f6.
Report an issue: GitHub.