{"record":{"id":"01b1f0d471c70bbf","repo":"nautechsystems/nautilus_trader","slug":"heartbeat-request-timeout-should-fit-in-an-instant","errorCode":null,"errorMessage":"heartbeat request timeout should fit in an instant","messagePattern":"heartbeat request timeout should fit in an instant","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/adapters/polymarket/src/execution/lifecycle.rs","lineNumber":756,"sourceCode":"    let mut interval = tokio::time::interval(HEARTBEAT_INTERVAL);\n    interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);\n    let mut heartbeat_id = String::new();\n    let mut request_failures = 0;\n    let mut last_acknowledged = None;\n\n    loop {\n        tokio::select! {\n            () = cancellation.cancelled() => break,\n            _ = interval.tick() => {}\n        }\n\n        let mut resynchronized = false;\n\n        loop {\n            let now = tokio::time::Instant::now();\n            let request_timeout = now\n                .checked_add(HEARTBEAT_REQUEST_TIMEOUT)\n                .expect(\"heartbeat request timeout should fit in an instant\");\n            let health_deadline = last_acknowledged.map(|acknowledged: tokio::time::Instant| {\n                acknowledged\n                    .checked_add(heartbeat_health_timeout)\n                    .expect(\"heartbeat health timeout should fit in an instant\")\n            });\n\n            if health_deadline.is_some_and(|deadline| deadline <= now) {\n                log::error!(\"Polymarket heartbeat health deadline elapsed\");\n                healthy.store(false, Ordering::Release);\n                return;\n            }\n\n            let request_deadline =\n                health_deadline.map_or(request_timeout, |deadline| deadline.min(request_timeout));\n            let response = tokio::select! {\n                () = cancellation.cancelled() => return,\n                response = tokio::time::timeout_at(\n                    request_deadline,","sourceCodeStart":738,"sourceCodeEnd":774,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/lifecycle.rs#L738-L774","documentation":"In the Polymarket heartbeat loop, each iteration computes a request deadline as current instant + HEARTBEAT_REQUEST_TIMEOUT via checked_add. The expect fires if the addition overflows tokio's Instant range, which normally cannot happen unless the process clock jumps far into the future or the timeout constant is astronomically large.","triggerScenarios":"run_heartbeats computing now + HEARTBEAT_REQUEST_TIMEOUT when the monotonic base instant is near its maximum — caused by extreme clock adjustments after VM pause/resume or corrupted monotonic time sources.","commonSituations":"Long-lived processes on hosts with unstable clock sources; VM/container migrations that reset monotonic time; nightly CI boxes resuming from suspend.","solutions":["Restart the process after the host clock has stabilized.","Fix the host's timekeeping (disable aggressive clock stepping, ensure stable TSC/KVM clock).","If patching, clamp the deadline instead of panicking: use min(now + timeout, Instant far-future bound)."],"exampleFix":"// before\nlet request_timeout = now\n    .checked_add(HEARTBEAT_REQUEST_TIMEOUT)\n    .expect(\"heartbeat request timeout should fit in an instant\");\n\n// after (defensive)\nlet request_timeout = now\n    .checked_add(HEARTBEAT_REQUEST_TIMEOUT)\n    .unwrap_or_else(|| tokio::time::Instant::now() + HEARTBEAT_REQUEST_TIMEOUT);","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// supervise the heartbeat task and restart it if it dies\nif let Err(e) = heartbeat_task.await {\n    log::warn!(\"heartbeat task crashed ({e:?}); restarting\");\n}","preventionTips":["Run long-lived processes on hosts with stable monotonic clocks (avoid aggressive clock stepping).","Supervise and restart background tasks so a single panic cannot end the client.","After VM resume/migration, restart the trader rather than trusting stale timers."],"tags":["rust","panic","polymarket","heartbeat","time","overflow"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}