nautechsystems/nautilus_trader · error

DurationNanos overflow in from_hours

Error message

DurationNanos overflow in from_hours

What it means

`DurationNanos::from_hours` converts whole hours (u64) to nanoseconds and panics when `hours * 3_600 * 1_000_000_000` exceeds `DurationNanos::MAX`. The panic arm replaces the Err of `try_from_hours` because this constructor is documented and designed to be usable in const contexts.

Source

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

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

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

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

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

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use `DurationNanos::try_from_hours(hours)` and handle Err.
  2. Bound-check `hours <= u64::MAX / 3_600_000_000_000` before calling.
  3. Clamp to `DurationNanos::MAX` for 'forever' semantics.
  4. Fix the upstream unit so the value is in hours.

Example fix

// before
let dur = DurationNanos::from_hours(retention_hours);

// after
let dur = DurationNanos::try_from_hours(retention_hours)
    .map_err(|_| ConfigError::OutOfRange("retention_hours"))?;
Defensive patterns

Strategy: validation

Validate before calling

const MAX_FROM_HOURS: u64 = u64::MAX / 3_600_000_000_000;
fn can_convert_hours(h: u64) -> bool { h <= MAX_FROM_HOURS }

Type guard

fn fits_duration_hours(h: u64) -> Option<DurationNanos> {
    DurationNanos::try_from_hours(h).ok()
}

Prevention

When it happens

Trigger: Calling `DurationNanos::from_hours(h)` with `h > u64::MAX / 3_600_000_000_000` (i.e. `h >= 5_124_095_576` hours, about 584 years), so `try_from_hours` fails and the match panics.

Common situations: Config values like 'retention_hours' or 'session_hours' set to u64::MAX as a sentinel for 'never expire'; unit mix-ups (minutes/seconds passed as hours); extreme-value tests.

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/23d085538191fa34. Report an issue: GitHub.