astrid-runtime/astrid · error
WinFsp stop deadline overflow
Error message
WinFsp stop deadline overflow
What it means
Raised in `stop_daemon` (crates/astrid-storage-provider-winfsp/src/win.rs:672) when `Instant::checked_add(DAEMON_STOP_TIMEOUT, now)` returns `None`, i.e. computing the post-stop polling deadline overflows the `tokio::time::Instant` range. This is effectively unreachable in practice (it requires a near-max timestamp) and is a defensive guard so deadline arithmetic never silently wraps into a poll loop that would spin until the 'endpoint remained live' bail.
Source
Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:672
.context("send WinFsp stop")?;
stream.flush().await.context("flush WinFsp stop")?;
let mut acknowledgement = [0_u8; 1];
stream
.read_exact(&mut acknowledgement)
.await
.context("read WinFsp stop acknowledgement")?;
if acknowledgement[0] != b'S' {
bail!("WinFsp daemon returned an invalid stop acknowledgement");
}
Result::<()>::Ok(())
};
tokio::time::timeout(DAEMON_STOP_TIMEOUT, stop)
.await
.map_err(|_| anyhow::anyhow!("WinFsp stop timed out"))??;
let deadline = tokio::time::Instant::now()
.checked_add(DAEMON_STOP_TIMEOUT)
.ok_or_else(|| anyhow::anyhow!("WinFsp stop deadline overflow"))?;
while endpoint_is_present(control_path) {
if tokio::time::Instant::now() >= deadline {
bail!("WinFsp control endpoint remained live after stop");
}
tokio::time::sleep(Duration::from_millis(25)).await;
}
Ok(())
}
fn initialize_winfsp() -> Result<()> {
load_adjacent_winfsp().context("load co-installed WinFsp runtime")?;
winfsp_wrs::init().context("initialize installed WinFsp runtime")
}
fn load_adjacent_winfsp() -> Result<()> {
let Some(directory) = std::env::current_exe()
.ok()
.and_then(|path| path.parent().map(Path::to_path_buf))View on GitHub (pinned to affd8760f4)
Solutions
- Treat it as an environmental clock anomaly: reboot the host or fix the monotonic clock source.
- In tests, avoid advancing tokio time to near-`Instant` saturation before calling `stop_daemon`.
- If it recurs on real hardware, update the tokio runtime; file a bug including the runtime/clock details.
- As a workaround, compute the deadline with `saturating_add` semantics by clamping the timeout.
Example fix
// before
let deadline = tokio::time::Instant::now()
.checked_add(DAEMON_STOP_TIMEOUT)
.ok_or_else(|| anyhow::anyhow!("WinFsp stop deadline overflow"))?;
// after (saturating alternative)
let deadline = tokio::time::Instant::now()
.checked_add(DAEMON_STOP_TIMEOUT)
.unwrap_or_else(tokio::time::Instant::now);
let deadline = deadline + Duration::from_millis(1); Defensive patterns
Strategy: fallback
Validate before calling
// Only relevant in tests using paused tokio time: assert!(tokio::time::Instant::now().checked_add(DAEMON_STOP_TIMEOUT).is_some());
Try / catch
let deadline = tokio::time::Instant::now()
.checked_add(DAEMON_STOP_TIMEOUT)
.ok_or_else(|| anyhow::anyhow!("WinFsp stop deadline overflow"))?;
// callers: treat as environment failure and abort teardown with diagnostics
match stop_daemon(&control_path).await {
Err(e) if e.to_string().contains("deadline overflow") => {
error!("clock anomaly detected; reboot/fix monotonic clock");
},
other => { other?; }
} Prevention
- Avoid advancing tokio test time to near-Instant saturation before invoking stop paths.
- Treat this as a host clock anomaly; verify the monotonic clock on affected machines.
- Prefer saturating deadline arithmetic in new code paths where a bounded delay suffices.
When it happens
Trigger: Specifically: `tokio::time::Instant::now().checked_add(DAEMON_STOP_TIMEOUT)` yields `None`. This requires the current monotonic instant plus `DAEMON_STOP_TIMEOUT` to exceed the internal representable maximum — an extreme/edge runtime-clock situation, not a user-fixable configuration issue.
Common situations: Essentially never seen by end users; it could only appear with a pathological monotonic clock value (e.g. u64::MAX-adjacent tick on an embedded/VM host with a broken clock, or after enormous fake-time offsets in tests using paused/auto-advance tokio time).
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- WinFsp control endpoint remained live after stop
- WinFsp stop timed out
- WinFsp mountpoint did not become ready within {} seconds: {}
- WinFsp daemon returned an invalid stop acknowledgement
- timed out waiting for capsule command result
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/c06141d833a7531d.
Report an issue: GitHub.