nautechsystems/nautilus_trader · error · anyhow::Error
Interval exceeds u64 nanoseconds
Error message
Interval exceeds u64 nanoseconds
What it means
duration_to_nanos converts a std Duration into a DurationNanos (u64 nanoseconds). Durations longer than u64::MAX nanoseconds (~584 years) cannot be represented, so TryFrom fails and the function returns 'Interval exceeds u64 nanoseconds'. It is used by set_timer for timer intervals.
Source
Thrown at crates/common/src/clock.rs:710
}
type SetTimeAlertNsHandler<'a> =
dyn Fn(&str, UnixNanos, Option<TimeEventCallback>, Option<bool>) -> anyhow::Result<()> + 'a;
type NextTimeNsHandler<'a> = dyn Fn(&str) -> Option<UnixNanos> + 'a;
type SetTimerNsHandler<'a> = dyn Fn(
&str,
DurationNanos,
Option<UnixNanos>,
Option<UnixNanos>,
Option<TimeEventCallback>,
Option<bool>,
Option<bool>,
) -> anyhow::Result<()>
+ 'a;
fn duration_to_nanos(duration: Duration) -> anyhow::Result<DurationNanos> {
DurationNanos::try_from(duration)
.map_err(|_| anyhow::anyhow!("Interval exceeds u64 nanoseconds"))
}
/// Registry for timer event callbacks.
///
/// Provides shared callback registration and retrieval logic used by both
/// `TestClock` and `LiveClock`.
#[derive(Debug, Default)]
pub struct CallbackRegistry {
default_callback: Option<TimeEventCallback>,
callbacks: AHashMap<Ustr, TimeEventCallback>,
}
impl CallbackRegistry {
/// Creates an empty callback registry.
#[must_use]
pub fn new() -> Self {
Self::default()
}View on GitHub (pinned to 18893faf8b)
Solutions
- Clamp or validate the interval before calling set_timer (e.g. cap at a sane maximum like Duration::from_secs(u64::MAX / 1_000_000_000)).
- Fix the interval computation so it cannot overflow — compute in u128 or use checked_mul when converting seconds/millis to nanoseconds.
- If 'never fire' semantics are needed, model it explicitly (no timer) rather than passing a gigantic Duration.
- Propagate the anyhow error from set_timer and surface a clear configuration message instead of panicking.
Example fix
// before
let interval = Duration::from_secs(years * 365 * 24 * 3600);
clock.set_timer(name, callback, start, interval)?; // may overflow u64 ns
// after
let interval = Duration::from_secs(
(years as u128 * 365 * 24 * 3600).min(u64::MAX as u128 / 1_000_000_000) as u64,
);
clock.set_timer(name, callback, start, interval)?; Defensive patterns
Strategy: validation
Validate before calling
# Rust
const MAX_INTERVAL: Duration = Duration::from_secs(u64::MAX / 1_000_000_000);
fn validate_interval(d: Duration) -> anyhow::Result<()> {
anyhow::ensure!(d <= MAX_INTERVAL, "interval {d:?} exceeds u64 nanoseconds");
Ok(())
} Type guard
fn fits_u64_nanos(d: Duration) -> bool {
d.as_secs() <= u64::MAX / 1_000_000_000
} Try / catch
match clock.set_timer(name, callback, start, interval) {
Ok(()) => {},
Err(e) if e.to_string().contains("exceeds u64 nanoseconds") => {
tracing::error!("timer interval too large: {e}; clamping");
}
Err(e) => return Err(e),
} Prevention
- Compute durations with checked arithmetic (checked_mul) when converting from seconds/millis to nanos.
- Cap configured timer intervals to a sane maximum in config validation.
- Represent 'infinite/never' timeouts explicitly instead of giant Duration values.
When it happens
Trigger: Calling set_timer (on TestClock or LiveClock) with a Duration whose nanosecond count exceeds u64::MAX — e.g. programmatically built durations like Duration::from_secs(u64::MAX) or huge multiplier arithmetic that overflows the nanosecond range.
Common situations: Config parsers computing timer intervals with overflow (seconds * 1e9 in a wider type then converting); sentinel 'infinite' timeouts encoded as enormous durations; fuzz/property tests generating extreme Duration 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
- Cannot represent durations greater than 584 years
- Event '{}' should have associated handler
- DurationNanos overflow in from_micros
- {e}
- Timer '{name}' alert time {} was in the past (current time i
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/771cd98c7e633a3a.
Report an issue: GitHub.