{"record":{"id":"6bee417c59bd28da","repo":"nautechsystems/nautilus_trader","slug":"book-snapshot-timer-start-exceeds-unixnanos-range","errorCode":null,"errorMessage":"Book snapshot timer start exceeds UnixNanos range","messagePattern":"Book snapshot timer start exceeds UnixNanos range","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/data/src/engine/mod.rs","lineNumber":4415,"sourceCode":"            }\n        }\n\n        BookSnapshotUnsubscribeResult::Removed\n    }\n\n    fn schedule_book_snapshotter(\n        &mut self,\n        interval_ms: NonZeroUsize,\n        snapshot_infos: BookSnapshotInfos,\n    ) {\n        let interval_ms_u64 =\n            u64::try_from(interval_ms.get()).expect(\"Snapshot interval exceeds u64\");\n        let interval_ns = DurationNanos::from_millis(interval_ms_u64);\n        let now_ns = self.clock.borrow().timestamp_ns();\n        let start_time_ns = now_ns\n            .floor(interval_ns)\n            .checked_add(interval_ns)\n            .expect(\"Book snapshot timer start exceeds UnixNanos range\");\n\n        let snapshotter = Rc::new(BookSnapshotter::new(\n            interval_ms,\n            snapshot_infos,\n            self.cache.clone(),\n        ));\n        let timer_name = snapshotter.timer_name;\n        let snapshotter_callback = snapshotter.clone();\n        let callback_fn: Rc<dyn Fn(TimeEvent)> =\n            Rc::new(move |event| snapshotter_callback.snapshot(event));\n        let callback = TimeEventCallback::from(callback_fn);\n\n        self.clock\n            .borrow_mut()\n            .set_timer_ns(\n                &timer_name,\n                interval_ns,\n                Some(start_time_ns),","sourceCodeStart":4397,"sourceCodeEnd":4433,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/data/src/engine/mod.rs#L4397-L4433","documentation":"DataEngine::schedule_book_snapshotter computes the first order-book snapshot timer start by flooring the current Unix nanos to the snapshot interval and adding one interval. checked_add returns None when that start time would exceed the UnixNanos range (u64 nanoseconds), and this expect turns that overflow into a panic. The library throws it because scheduling a timer beyond the representable time domain is unrecoverable in the engine.","triggerScenarios":"Calling book snapshot subscribe APIs (which reach schedule_book_snapshotter) when clock.timestamp_ns() is so large that now_ns.floor(interval_ns) + interval_ns overflows u64 nanoseconds; also reachable with a TestClock set to a nanos value near u64::MAX, or an extremely large interval_ms that pushes the floored value over the limit.","commonSituations":"Unit tests that advance a TestClock to absurdly large timestamps near u64::MAX; misconfigured clock sources producing huge nanos values; snapshot intervals combined with a current time at the edge of the representable range.","solutions":["Verify the clock timestamp is a realistic Unix time (roughly 1e18 nanoseconds, not near u64::MAX) before subscribing to book snapshots","In tests, avoid advancing the TestClock to values near u64::MAX when snapshot intervals are active","If a custom clock source is in use, fix its timestamp computation so it returns valid Unix nanoseconds","Use a smaller snapshot interval_ms so floor(now) + interval stays within range, though overflow only occurs at extreme timestamps"],"exampleFix":"// before\nlet start_time_ns = now_ns\n    .floor(interval_ns)\n    .checked_add(interval_ns)\n    .expect(\"Book snapshot timer start exceeds UnixNanos range\");\n// after\nlet start_time_ns = now_ns\n    .floor(interval_ns)\n    .checked_add(interval_ns)\n    .ok_or_else(|| DataEngineError::ConfigError(format!(\n        \"Snapshot timer start {now_ns} + {interval_ns}ns exceeds UnixNanos range\"\n    )))?;","handlingStrategy":"validation","validationCode":"let now_ns = clock.timestamp_ns();\nlet interval_ns = u64::from(interval_ms_u64) * 1_000_000;\nassert!(now_ns.checked_add(interval_ns).is_some(), \"clock time plus snapshot interval exceeds UnixNanos range\");","typeGuard":"fn unix_nanos_fits(now_ns: u64, interval_ns: u64) -> bool {\n    now_ns.checked_add(interval_ns).is_some()\n}","tryCatchPattern":null,"preventionTips":["Keep clock timestamps within realistic Unix nanos ranges in production and tests","Avoid advancing TestClock to values near u64::MAX when timers are scheduled","Audit custom clock implementations for timestamp computation bugs"],"tags":["rust","panic","integer-overflow","timer","clock"],"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"}