Summary
ant-node 0.14.2 panics and aborts with overflow when subtracting duration from instant (std time.rs:445) when launched shortly after Windows boots — i.e. the recommended auto-start-service setup. Operators without SCM recovery configured lose the node on every reboot; with recovery, the second start succeeds because uptime by then exceeds the offending window (which is what we observed).
We traced the reachable call site to saorsa-transport 0.35.1 (the exact version in this repo's Cargo.lock). The same bug class hit x0xd on the same host via its parallel fork of the same code — canonical analysis and fix patterns in the companion issue: saorsa-labs/x0x#190.
Mechanism (short — full version in companion issue)
On Windows std::time::Instant counts from boot (QPC). Instant::now() - duration panics whenever duration > uptime. ant-node builds with panic = "abort", so one underflow kills the node (Windows exception 0xC0000409 / __fastfail).
Observed failure
|
|
| Host |
Windows 10 Pro N for Workstations 19045 |
| Binary |
ant-node 0.14.2 (release), PE link timestamp 2026-07-01, WinSW auto-start service, SYSTEM |
| Config |
production network, --port 12003, storage on a dedicated HDD volume |
| Boot |
2026-07-06 17:25:11 UTC |
| ant-node start |
17:25:28 UTC (uptime 17 s) |
| Abort |
17:25:35 UTC (uptime 24 s) |
Service stderr (the panic printed twice — two threads hit it):
The application panicked (crashed).
Message: overflow when subtracting duration from instant
Location: /rustc/31fca3adb283cc9dfd56b49cdee9a96eb9c96ffd/library\std\src\time.rs:445
WER recorded exception 0xc0000409 at module offset 0x9e0675, fault bucket 2300527752312831529 (BEX64); WinSW logged exit code -1073740791. SCM recovery restarted the node 48 s later and that instance ran fine — consistent with the underflow window having passed. Crash minidumps exist and can be shared privately (we'd rather not attach process memory of a rewards-earning node publicly).
Call site (verified in saorsa-transport 0.35.1, as pinned by ant-node 0.14.2's Cargo.lock via saorsa-core 0.26.2)
src/connection/nat_traversal.rs:766 and :777:
fn cleanup_rate_tracker(&mut self, now: Instant) {
let cutoff = now - self.rate_window; // rate_window = 60 s → panics at uptime < 60 s
...
fn cleanup_coordination_tracker(&mut self, now: Instant) {
let cutoff = now - self.rate_window;
Reached via add_remote_candidate / observe_peer_address when the first NAT-traversal or OBSERVED_ADDRESS frame arrives — for a bootstrap-connected node that happens within seconds of start. This is the only reachable Instant - Duration with a >20 s window in the ant-node + saorsa-core + saorsa-transport tree (we grepped all three at the pinned versions; everything else is test code or millisecond-scale).
Worth noting: saorsa-core's own test suite contains an explicit comment about exactly this platform hazard (src/dht/core_engine.rs:3596), and upstream quinn fixed the same pattern in its loss detector via quinn PR #2436 — the codebase family knows the pattern; these two functions just missed it.
Suggested fix
// invert the comparison — only Instant − Instant, saturating since Rust 1.60 (quinn PR #2436's approach)
while let Some(&front_time) = self.candidate_rate_tracker.front() {
if now.saturating_duration_since(front_time) > self.rate_window {
self.candidate_rate_tracker.pop_front();
} else { break; }
}
// or: let Some(cutoff) = now.checked_sub(self.rate_window) else { return; };
Reproduction
- Install ant-node as an auto-start Windows service (WinSW/sc.exe), connected to the production network.
- Reboot.
- Node aborts within ~30 s of boot (2/2 boots on our host). Configure SCM recovery and the second start succeeds — which also means the bug hides from operators who look a minute later.
We can run a boot cycle with RUST_BACKTRACE=full to pin the exact trace, and can test a patched build on the reproducing host.
Related but separate reports from the same 24 h on this node: a deterministic JoinHandle polled after completion abort in saorsa-transport's MASQUE relay teardown, and a silent whole-node stall at the UTC-midnight log rotation — filed separately: WithAutonomi/saorsa-transport#108 and #166.
Summary
ant-node0.14.2 panics and aborts withoverflow when subtracting duration from instant(stdtime.rs:445) when launched shortly after Windows boots — i.e. the recommended auto-start-service setup. Operators without SCM recovery configured lose the node on every reboot; with recovery, the second start succeeds because uptime by then exceeds the offending window (which is what we observed).We traced the reachable call site to
saorsa-transport0.35.1 (the exact version in this repo's Cargo.lock). The same bug class hitx0xdon the same host via its parallel fork of the same code — canonical analysis and fix patterns in the companion issue: saorsa-labs/x0x#190.Mechanism (short — full version in companion issue)
On Windows
std::time::Instantcounts from boot (QPC).Instant::now() - durationpanics wheneverduration > uptime.ant-nodebuilds withpanic = "abort", so one underflow kills the node (Windows exception0xC0000409/__fastfail).Observed failure
ant-node 0.14.2(release), PE link timestamp 2026-07-01, WinSW auto-start service, SYSTEM--port 12003, storage on a dedicated HDD volumeService stderr (the panic printed twice — two threads hit it):
WER recorded exception
0xc0000409at module offset0x9e0675, fault bucket2300527752312831529(BEX64); WinSW logged exit code-1073740791. SCM recovery restarted the node 48 s later and that instance ran fine — consistent with the underflow window having passed. Crash minidumps exist and can be shared privately (we'd rather not attach process memory of a rewards-earning node publicly).Call site (verified in saorsa-transport 0.35.1, as pinned by ant-node 0.14.2's Cargo.lock via saorsa-core 0.26.2)
src/connection/nat_traversal.rs:766and:777:Reached via
add_remote_candidate/observe_peer_addresswhen the first NAT-traversal or OBSERVED_ADDRESS frame arrives — for a bootstrap-connected node that happens within seconds of start. This is the only reachableInstant - Durationwith a >20 s window in the ant-node + saorsa-core + saorsa-transport tree (we grepped all three at the pinned versions; everything else is test code or millisecond-scale).Worth noting: saorsa-core's own test suite contains an explicit comment about exactly this platform hazard (
src/dht/core_engine.rs:3596), and upstream quinn fixed the same pattern in its loss detector via quinn PR #2436 — the codebase family knows the pattern; these two functions just missed it.Suggested fix
Reproduction
We can run a boot cycle with
RUST_BACKTRACE=fullto pin the exact trace, and can test a patched build on the reproducing host.Related but separate reports from the same 24 h on this node: a deterministic
JoinHandle polled after completionabort in saorsa-transport's MASQUE relay teardown, and a silent whole-node stall at the UTC-midnight log rotation — filed separately: WithAutonomi/saorsa-transport#108 and #166.