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
- Fix the host system clock (sync via NTP, set correct date) and rerun
- If clock correctness cannot be guaranteed, replace SystemTime with a monotonic or library-injected clock
- Check `date`/`timedatectl` output before running the integrity check in scripts
- 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
- Sync the host clock via NTP and monitor time sync health
- Check `timedatectl`/clock sanity before long-running trading processes
- Avoid running integrity checks on freshly booted RTC-less machines before time sync
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
- Event '{}' should have associated handler
- BacktestEngine requires TestClock
- seconds timestamp should fit i64
- seconds timestamp should be within valid range
- AtomicTime overflow: reached u64::MAX
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b66de9fb47fb2405.
Report an issue: GitHub.