{"record":{"id":"d360396cc693208a","repo":"nautechsystems/nautilus_trader","slug":"time-event-accumulator-sequence-overflow","errorCode":null,"errorMessage":"Time event accumulator sequence overflow","messagePattern":"Time event accumulator sequence overflow","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/accumulator.rs","lineNumber":90,"sourceCode":"    }\n}\n\nimpl TimeEventAccumulator {\n    /// Creates a new [`TimeEventAccumulator`] instance.\n    #[must_use]\n    pub fn new() -> Self {\n        Self {\n            heap: BinaryHeap::new(),\n            next_sequence: 0,\n        }\n    }\n\n    fn push(&mut self, handler: TimeEventHandler) {\n        let sequence = self.next_sequence;\n        self.next_sequence = self\n            .next_sequence\n            .checked_add(1)\n            .expect(\"Time event accumulator sequence overflow\");\n        self.heap\n            .push(Reverse(AccumulatedTimeEventHandler { handler, sequence }));\n    }\n\n    /// Advance the given clock to the `to_time_ns` and push events to the heap.\n    pub fn advance_clock(&mut self, clock: &mut TestClock, to_time_ns: UnixNanos, set_time: bool) {\n        let events = clock.advance_time(to_time_ns, set_time);\n        let handlers = clock.match_handlers(events);\n        for handler in handlers {\n            self.push(handler);\n        }\n    }\n\n    /// Peek at the next event timestamp without removing it.\n    ///\n    /// Returns `None` if the heap is empty.\n    #[must_use]\n    pub fn peek_next_time(&self) -> Option<UnixNanos> {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/accumulator.rs#L72-L108","documentation":"TimeEventAccumulator::push assigns each queued time event handler a monotonically increasing u64 sequence number used as a FIFO tie-breaker in the min-heap. The sequence counter is incremented with checked_add, and this panic fires only after u64::MAX pushes have occurred, exhausting the sequence space. It is effectively an internal invariant that can never be hit in a realistic backtest.","triggerScenarios":"Calling push (directly or via advance_clock) approximately 2^64 times within the lifetime of a single TimeEventAccumulator instance; no realistic workload reaches this.","commonSituations":"Only conceivable in an extremely long-running backtest with an unbounded timer-scheduling loop, or in a custom/stress test that intentionally drives next_sequence to u64::MAX. Not a real-world configuration or usage issue.","solutions":["Treat as an internal invariant; no user action is needed for realistic workloads","Split work across multiple accumulator instances if an astronomically long run is genuinely required","Report to maintainers if encountered, since reaching u64::MAX sequences indicates a runaway event loop"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Not guardable by users; a u64 sequence overflow requires ~2^64 pushes.\n// Assert sanity in long-running jobs:\nassert!(accumulator_events_pushed < u64::MAX / 2, \"runaway event loop suspected\");","typeGuard":null,"tryCatchPattern":"// Panics are not catchable in normal Rust; ensure the event loop terminates.\nif events_pushed > threshold { log::error!(\"unbounded timer scheduling detected\"); std::process::abort(); }","preventionTips":["Ensure timer rescheduling loops have termination conditions","Monitor event counts in long-running backtests","Report any occurrence to maintainers — it indicates a runaway loop, not normal usage"],"tags":["rust","panic","overflow","backtest","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}