nautechsystems/nautilus_trader · critical

System time overflow: value exceeds u64::MAX nanoseconds

Error message

System time overflow: value exceeds u64::MAX nanoseconds

What it means

nanos_since_unix_epoch in crates/core/src/time.rs:136 converts the duration since the Unix epoch to u64 nanoseconds, panicking via expect("System time overflow: value exceeds u64::MAX nanoseconds") when the value exceeds u64::MAX. Since u64 nanoseconds cover roughly the year 2554, this fires only when the system clock is set absurdly far in the future (or a mocked clock misbehaves), which the documented invariant treats as an unrecoverable environment error.

Source

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

        // running under simulation are always inside a runtime, so they
        // continue to receive virtual time.
        match madsim::time::TimeHandle::try_current() {
            Some(handle) => handle.now_time(),
            None => SystemTime::now(),
        }
    }
}

/// Returns the current UNIX time in nanoseconds, based on [`SystemTime::now()`].
///
/// # Panics
///
/// Panics if the duration in nanoseconds exceeds `u64::MAX`.
#[inline(always)]
#[must_use]
pub fn nanos_since_unix_epoch() -> u64 {
    u64::try_from(duration_since_unix_epoch().as_nanos())
        .expect("System time overflow: value exceeds u64::MAX nanoseconds")
}

/// Represents an atomic timekeeping structure.
///
/// [`AtomicTime`] can act as a real-time clock or static clock based on its mode.
/// It uses an [`AtomicU64`] to atomically update the value using only immutable
/// references.
///
/// The `realtime` flag indicates which mode the clock is currently in.
/// For concurrency, this struct uses atomic operations with appropriate memory orderings:
/// - **Acquire/Release** for reading/writing in **static mode**.
/// - **Compare-and-exchange (`AcqRel`)** in real-time mode to guarantee monotonic increments.
///
/// The mode flag and timestamp are private so every update flows through the methods
/// that uphold the monotonicity and mode invariants.
#[repr(C)]
#[derive(Debug)]
pub struct AtomicTime {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Correct the system clock (NTP sync) and verify with `date` before restarting the process.
  2. Check any simulation/virtual clock seeding code: confirm the epoch offset unit (seconds vs millis vs nanos) and magnitude.
  3. If a fake clock is used in tests, clamp its advancement so accumulated time stays within u64 nanoseconds.
  4. Audit NTP sources and time-jump handling; log the clock value at startup to catch absurd settings early.

Example fix

# before (virtual clock seeded in nanos instead of seconds)
start = 1_700_000_000_000_000_000 * 1_000  # runaway offset
# after
start = 1_700_000_000  # seconds since epoch, correct unit
Defensive patterns

Strategy: validation

Validate before calling

use std::time::{SystemTime, UNIX_EPOCH};
let d = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
assert!(u64::try_from(d.as_nanos()).is_ok(), "clock value exceeds u64 nanos; check clock config");

Type guard

fn nanos_fit_u64(d: std::time::Duration) -> bool {
    u64::try_from(d.as_nanos()).is_ok()
}

Prevention

When it happens

Trigger: Calling nanos_since_unix_epoch (via run_impl, abort_run, end, is_within_last_24_hours, etc.) when the OS clock is set past ~year 2554: manual date misconfiguration, NTP serving a wildly wrong time, or a test/virtual clock configured with an out-of-range epoch offset.

Common situations: Typo'd manual date setting (e.g. year 30000); misconfigured mock clock fixtures advancing virtual time by huge multiples; broken NTP servers; deterministic simulation clocks seeded with milliseconds instead of seconds (or vice versa) producing runaway 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/06abc81bd01743b1. Report an issue: GitHub.