nautechsystems/nautilus_trader · error

Cannot increment time beyond u64::MAX

Error message

Cannot increment time beyond u64::MAX

What it means

`increment_time` on the static/test clock advances the internal `timestamp_ns` (an atomic u64) by the given delta using checked addition. When the addition would overflow u64::MAX, the CAS update fails and the method bails with this error instead of silently wrapping time. It preserves the invariant that the simulated clock is monotonically increasing and never wraps.

Source

Thrown at crates/core/src/time.rs:293

    /// The mode check is not atomic with the subsequent update. If another thread calls
    /// `make_realtime()` between the check and update, the invariant can be violated.
    /// This is intentional: mode switching is a setup-time operation and should not
    /// occur concurrently with time operations. Callers must ensure mode switches are
    /// complete before resuming time operations.
    pub fn increment_time(&self, delta: DurationNanos) -> anyhow::Result<UnixNanos> {
        anyhow::ensure!(
            !self.realtime.load(Ordering::SeqCst),
            "Cannot increment time while clock is in realtime mode"
        );

        let previous =
            match self
                .timestamp_ns
                .try_update(Ordering::AcqRel, Ordering::Acquire, |current| {
                    current.checked_add(delta.as_u64())
                }) {
                Ok(prev) => prev,
                Err(_) => anyhow::bail!("Cannot increment time beyond u64::MAX"),
            };

        debug_assert!(
            !self.realtime.load(Ordering::SeqCst),
            "Invariant: clock must remain in static mode across `increment_time`"
        );

        Ok(UnixNanos::from(previous) + delta)
    }

    /// Retrieves and updates the current "real-time" clock, returning a strictly increasing
    /// timestamp based on system time.
    ///
    /// Internally:
    /// - We fetch `now` from [`SystemTime::now()`].
    /// - We do an atomic compare-and-exchange (using [`Ordering::AcqRel`]) to ensure the stored
    ///   timestamp is never less than the last timestamp.
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Reduce the size or number of increments so the accumulated time stays far below u64::MAX
  2. Reinitialize the static clock to a smaller starting timestamp
  3. Use the realtime clock if you need wall-clock time rather than arbitrary increments
  4. Catch the error and treat it as end-of-simulation in test harnesses

Example fix

// before
clock.increment_time(TimeDelta::from_nanos(u64::MAX))?; // overflows
// after
let delta = TimeDelta::from_secs(1);
if clock.timestamp_ns() > u64::MAX - delta.as_u64() {
    // stop or reset the clock before incrementing
} else {
    clock.increment_time(delta)?;
}
Defensive patterns

Strategy: try-catch

Validate before calling

let delta_u64 = delta.as_u64();
if clock.timestamp_ns() > u64::MAX - delta_u64 {
    // skip, reset clock, or end simulation
}

Type guard

fn can_increment(current_ns: u64, delta_ns: u64) -> bool {
    current_ns.checked_add(delta_ns).is_some()
}

Try / catch

match clock.increment_time(delta) {
    Ok(prev) => /* continue */,
    Err(e) => tracing::warn!("clock exhausted: {e}"), // end-of-simulation handling
}

Prevention

When it happens

Trigger: Calling `increment_time` with a delta such that current_ns + delta > u64::MAX (≈1.8e19 ns). In practice: repeatedly advancing a long-running static clock by huge deltas, or one call with an astronomically large `TimeDelta`/nanosecond value.

Common situations: Backtests that add many large increments to a clock initialized near u64::MAX; unit tests or fuzzers that pass u64::MAX deltas; miscomputed deltas (nanoseconds vs seconds confusion producing enormous values).

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/5beba2c0d7a205a3. Report an issue: GitHub.