nautechsystems/nautilus_trader · error

Time went backwards

Error message

Time went backwards

What it means

The integrity check captures the start timestamp with SystemTime::now().duration_since(UNIX_EPOCH) and expects it to succeed. If the OS reports a time before the Unix epoch, duration_since returns Err and this expect panics. It guards against a fundamentally broken system clock.

Source

Thrown at crates/common/src/cache/mod.rs:3027

    }

    /// Checks integrity of data within the cache.
    ///
    /// All data should be loaded from the database prior to this call.
    /// If an error is found then a log error message will also be produced.
    ///
    /// # Panics
    ///
    /// Panics if failure calling system clock.
    #[must_use]
    pub fn check_integrity(&mut self) -> bool {
        let mut error_count = 0;
        let failure = "Integrity failure";

        // Get current timestamp in microseconds
        let timestamp_us = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("Time went backwards")
            .as_micros();

        log::info!("Checking data integrity");

        // Check object caches
        for account_id in self.accounts.keys() {
            if !self
                .index
                .venue_account
                .contains_key(&account_id.get_issuer())
            {
                log::error!(
                    "{failure} in accounts: {account_id} not found in `self.index.venue_account`",
                );
                error_count += 1;
            }
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Fix the host system clock (sync via NTP, set correct date) and rerun
  2. If clock correctness cannot be guaranteed, replace SystemTime with a monotonic or library-injected clock
  3. Check `date`/`timedatectl` output before running the integrity check in scripts
  4. Guard the call site: if time is before UNIX_EPOCH, skip or delay the integrity check

Example fix

// before
let timestamp_us = SystemTime::now()
    .duration_since(UNIX_EPOCH)
    .expect("Time went backwards")
    .as_micros();
// after
let timestamp_us = SystemTime::now()
    .duration_since(UNIX_EPOCH)
    .map_err(|_| anyhow!("system clock is before UNIX_EPOCH; sync the clock"))?
    .as_micros();
Defensive patterns

Strategy: validation

Validate before calling

if SystemTime::now().duration_since(UNIX_EPOCH).is_err() {
    eprintln!("System clock is before UNIX_EPOCH; fix clock before integrity check");
    std::process::exit(1);
}

Try / catch

// Panics are not catchable; pre-validate the clock
match SystemTime::now().duration_since(UNIX_EPOCH) {
    Ok(t) => println!("clock ok: {}us", t.as_micros()),
    Err(e) => eprintln!("clock invalid: {e}"),
}

Prevention

When it happens

Trigger: Calling an integrity-check method (check_* on Cache) while the host clock is set earlier than 1970-01-01T00:00:00Z, e.g. during system boot with an unset RTC or a clock reset.

Common situations: Embedded systems or VMs without RTC battery starting with epoch 0 or an earlier default; container images with wrong clock; deliberate clock manipulation in tests; NTP failures leaving a bad system time.

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


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