nautechsystems/nautilus_trader · error
Time event accumulator sequence overflow
Error message
Time event accumulator sequence overflow
What it means
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.
Source
Thrown at crates/backtest/src/accumulator.rs:90
}
}
impl TimeEventAccumulator {
/// Creates a new [`TimeEventAccumulator`] instance.
#[must_use]
pub fn new() -> Self {
Self {
heap: BinaryHeap::new(),
next_sequence: 0,
}
}
fn push(&mut self, handler: TimeEventHandler) {
let sequence = self.next_sequence;
self.next_sequence = self
.next_sequence
.checked_add(1)
.expect("Time event accumulator sequence overflow");
self.heap
.push(Reverse(AccumulatedTimeEventHandler { handler, sequence }));
}
/// Advance the given clock to the `to_time_ns` and push events to the heap.
pub fn advance_clock(&mut self, clock: &mut TestClock, to_time_ns: UnixNanos, set_time: bool) {
let events = clock.advance_time(to_time_ns, set_time);
let handlers = clock.match_handlers(events);
for handler in handlers {
self.push(handler);
}
}
/// Peek at the next event timestamp without removing it.
///
/// Returns `None` if the heap is empty.
#[must_use]
pub fn peek_next_time(&self) -> Option<UnixNanos> {View on GitHub (pinned to 18893faf8b)
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
Defensive patterns
Strategy: retry
Validate before calling
// Not guardable by users; a u64 sequence overflow requires ~2^64 pushes. // Assert sanity in long-running jobs: assert!(accumulator_events_pushed < u64::MAX / 2, "runaway event loop suspected");
Try / catch
// Panics are not catchable in normal Rust; ensure the event loop terminates.
if events_pushed > threshold { log::error!("unbounded timer scheduling detected"); std::process::abort(); } Prevention
- 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
When it happens
Trigger: Calling push (directly or via advance_clock) approximately 2^64 times within the lifetime of a single TimeEventAccumulator instance; no realistic workload reaches this.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- next index is within the data batch
- index is within the data batch
- timer exists at timestamp
- Cannot handle command: {command:?}
- Latency model should be initialized
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d360396cc693208a.
Report an issue: GitHub.