nautechsystems/nautilus_trader · error

DurationNanos overflow in from_secs

Error message

DurationNanos overflow in from_secs

What it means

`DurationNanos::from_secs` converts whole seconds (u64) into nanoseconds. It panics when `secs * 1_000_000_000` exceeds `DurationNanos::MAX`, since the result cannot be stored in the u64 nanosecond representation. The panic is deliberate: this is the const, infallible-facing constructor documented as 'Panics if the result exceeds DurationNanos::MAX'.

Source

Thrown at crates/core/src/nanos.rs:152

    /// Creates a duration from a number of whole milliseconds.
    ///
    /// # Errors
    ///
    /// Returns an error if the result exceeds [`DurationNanos::MAX`].
    pub const fn try_from_millis(millis: u64) -> Result<Self, DurationNanosOutOfRangeError> {
        Self::try_from_units(millis, NANOSECONDS_IN_MILLISECOND, "milliseconds")
    }

    /// Creates a duration from a number of whole seconds.
    ///
    /// # Panics
    ///
    /// Panics if the result exceeds [`DurationNanos::MAX`].
    #[must_use]
    pub const fn from_secs(secs: u64) -> Self {
        match Self::try_from_secs(secs) {
            Ok(duration) => duration,
            Err(_) => panic!("DurationNanos overflow in from_secs"),
        }
    }

    /// Creates a duration from a number of whole seconds.
    ///
    /// # Errors
    ///
    /// Returns an error if the result exceeds [`DurationNanos::MAX`].
    pub const fn try_from_secs(secs: u64) -> Result<Self, DurationNanosOutOfRangeError> {
        Self::try_from_units(secs, NANOSECONDS_IN_SECOND, "seconds")
    }

    /// Creates a duration from a number of whole minutes.
    ///
    /// # Panics
    ///
    /// Panics if the result exceeds [`DurationNanos::MAX`].
    #[must_use]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use `DurationNanos::try_from_secs(secs)` and handle Err explicitly.
  2. Bound-check the input: reject values greater than `u64::MAX / 1_000_000_000` before construction.
  3. Clamp to `DurationNanos::MAX` when 'as long as possible' semantics are intended.
  4. Fix upstream units if the config value is already in nanoseconds/milliseconds.

Example fix

// before
let dur = DurationNanos::from_secs(ttl_secs);

// after
let dur = match DurationNanos::try_from_secs(ttl_secs) {
    Ok(d) => d,
    Err(_) => return Err(anyhow!("ttl_secs {ttl_secs} too large for DurationNanos")),
};
Defensive patterns

Strategy: validation

Validate before calling

const MAX_FROM_SECS: u64 = u64::MAX / 1_000_000_000;
fn can_convert_secs(s: u64) -> bool { s <= MAX_FROM_SECS }

Type guard

fn fits_duration_secs(s: u64) -> Option<DurationNanos> {
    DurationNanos::try_from_secs(s).ok()
}

Prevention

When it happens

Trigger: Calling `DurationNanos::from_secs(s)` with `s > u64::MAX / 1_000_000_000` (i.e. `s >= 18_446_744_073`, about 584 years), causing the checked multiplication inside `try_from_secs` to fail and the `Err(_)` arm to panic.

Common situations: Configuration values like 'ttl_seconds' or 'expiry_seconds' set absurdly high (e.g. u64::MAX as 'forever'); converting a lifetime or lease duration to seconds then feeding it in; test code probing extreme 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/4126c4adf2670c91. Report an issue: GitHub.