nautechsystems/nautilus_trader · error
Timer '{name}' next event time {} would be in the past (curr
Error message
Timer '{name}' next event time {} would be in the past (current time is {ts_now}) What it means
validate_and_prepare_timer checks that the computed first event time (start_time_ns + interval_ns) is not in the past. When it is and allow-past handling is disabled, the timer would never fire at the requested time, so set_timer_ns rejects the request instead of silently registering a dead timer.
Source
Thrown at crates/common/src/clock.rs:862
let name = Ustr::from(name);
let allow_past = allow_past.unwrap_or(true);
let fire_immediately = fire_immediately.unwrap_or(false);
let start_time_ns = start_time_ns
.filter(|start_time_ns| *start_time_ns != 0)
.unwrap_or(ts_now);
let next_event_time = if fire_immediately {
start_time_ns
} else {
start_time_ns.checked_add(interval_ns).ok_or_else(|| {
anyhow::anyhow!("Timer '{name}' first event time exceeds UnixNanos range")
})?
};
if !allow_past && next_event_time < ts_now {
anyhow::bail!(
"Timer '{name}' next event time {} would be in the past (current time is {ts_now})",
next_event_time.to_rfc3339(),
);
}
if let Some(stop_time) = stop_time_ns {
if stop_time <= start_time_ns {
anyhow::bail!(
"Timer '{name}' stop time {} must be after start time {}",
stop_time.to_rfc3339(),
start_time_ns.to_rfc3339(),
);
}
if !allow_past && stop_time <= ts_now {
anyhow::bail!(
"Timer '{name}' stop time {} is in the past (current time is {ts_now})",
stop_time.to_rfc3339(),View on GitHub (pinned to 18893faf8b)
Solutions
- Set start_time_ns to the current time (clock.timestamp_ns()) or a future instant before calling set_timer_ns.
- Enable the allow-past option if immediate firing of missed intervals is acceptable in your setup.
- Recompute the schedule relative to 'now' each time the strategy starts rather than persisting absolute start times.
- Catch the error and fall back to registering the timer with a now-based start time.
Example fix
// before
clock.set_timer_ns("my_timer", interval_ns, saved_start_time_ns);
// after
let now = clock.timestamp_ns();
let start = if saved_start_time_ns <= now { now } else { saved_start_time_ns };
clock.set_timer_ns("my_timer", interval_ns, start); Defensive patterns
Strategy: validation
Validate before calling
fn ensure_valid_timer_start(clock: &dyn Clock, start_time_ns: u64, interval_ns: u64) -> anyhow::Result<u64> {
let next = start_time_ns.checked_add(interval_ns)
.ok_or_else(|| anyhow::anyhow!("timer first event overflows UnixNanos"))?;
if next <= clock.timestamp_ns() {
anyhow::bail!("timer first event {next} would be in the past");
}
Ok(start_time_ns)
} Try / catch
match clock.set_timer_ns(name, interval_ns, start, stop, None, false, false) {
Ok(()) => {},
Err(e) if e.to_string().contains("would be in the past") => {
log::warn!("restarting timer at now: {e}");
clock.set_timer_ns(name, interval_ns, clock.timestamp_ns(), stop, None, false, false)?;
}
Err(e) => return Err(e),
} Prevention
- Compute start times relative to current clock time at registration, not persisted absolutes
- Check for u64 overflow when adding interval to start time
- Use allow_past deliberately when immediate catch-up firing is acceptable
- Verify all times are Unix nanoseconds, not seconds or milliseconds
When it happens
Trigger: Calling set_timer_ns with start_time_ns (plus interval_ns) earlier than clock.timestamp_ns() while allow_past is false — typically on a LiveClock.
Common situations: Reusing a saved timer spec across sessions; backtest-generated start times replayed live; slow startup so the process reaches timer registration after the intended start time; clock skew between machines.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Timer '{name}' alert time {} was in the past (current time i
- Timer '{name}' stop time {} is in the past (current time is
- Timer '{name}' stop time {} must be after start time {}
- Event '{}' should have associated handler
- system clock is before UNIX epoch
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ee2d0a3d68ae32ff.
Report an issue: GitHub.