nautechsystems/nautilus_trader · error
timer exists at timestamp
Error message
timer exists at timestamp
What it means
BacktestEngine::run_timer_handlers_at pops due time events from the accumulator after peeking that the accumulator's next time equals ts_event. The expect asserts the pop always succeeds right after the successful peek. Failure would mean the accumulator was drained between the peek and the pop, or peek/pop disagree — an internal consistency bug in the timer loop.
Source
Thrown at crates/backtest/src/engine.rs:1698
self.last_ns = t;
self.flush_accumulator_events(clocks, t)?;
Ok(false)
}
}
}
fn run_timer_handlers_at(
&mut self,
clocks: &[Rc<RefCell<dyn Clock>>],
ts_event: UnixNanos,
advance_to: UnixNanos,
) {
self.last_ns = ts_event;
while self.accumulator.peek_next_time() == Some(ts_event) {
let handler = self
.accumulator
.pop_next_at_or_before(ts_event)
.expect("timer exists at timestamp");
Self::set_all_clocks_time(clocks, ts_event);
logging_clock_set_static_time(ts_event.as_u64());
handler.run();
self.drain_command_queues();
if self.kernel.is_shutdown_requested() {
return;
}
for clock in clocks {
Self::advance_clock_on_accumulator(&mut self.accumulator, clock, advance_to, false);
}
}
}
fn finalize_timestamp(
&mut self,
clocks: &[Rc<RefCell<dyn Clock>>],View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure no code calls accumulator methods concurrently with engine time advancement
- File a minimal reproduction as a bug report if hit
- Upgrade to a version where the peek/pop mismatch is fixed
Defensive patterns
Strategy: type-guard
Validate before calling
// Users cannot peek/pop the accumulator directly; ensure timers are only scheduled // via the engine API and never cancelled externally mid-run: assert!(clock.timer_count() >= 0, "clock state sanity");
Try / catch
// Panic not catchable in normal Rust; reproduce with a timer-only backtest and report.
Prevention
- Schedule/cancel timers only through engine and clock public APIs
- Do not share the TestClock with code that mutates timers during a run
- Upgrade if a regression is reported upstream
When it happens
Trigger: Practically unreachable through the public run() API; would require peek_next_time() and pop_next_at_or_before() to disagree, e.g. via a logic regression or external mutation of the accumulator during the loop (called from advance_time_impl, flush_accumulator_events, finalize_timestamp).
Common situations: Only after an engine internals change/regression or a custom subclass interfering with the accumulator. Not a user configuration error.
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
- Time event accumulator sequence overflow
- next index is within the data batch
- index is within the data batch
- 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/d4e3e65823f9dc8f.
Report an issue: GitHub.