nautechsystems/nautilus_trader · error
Duration is longer than 584 years
Error message
Duration is longer than 584 years
What it means
The From<Duration> for Nanos conversion in the rate limiter stores time as u64 nanoseconds (governor-style). Any Duration longer than ~584 years cannot fit and the expect panics. This mirrors the underlying u64 nanosecond representation used by the GCRA algorithm.
Source
Thrown at crates/network/src/ratelimiter/nanos.rs:68
#[inline]
pub const fn saturating_add(self, rhs: Self) -> Self {
Self(self.0.saturating_add(rhs.0))
}
#[inline]
pub const fn saturating_mul(self, rhs: u64) -> Self {
Self(self.0.saturating_mul(rhs))
}
}
impl From<Duration> for Nanos {
fn from(d: Duration) -> Self {
// This will panic:
Self(
d.as_nanos()
.try_into()
.expect("Duration is longer than 584 years"),
)
}
}
impl Debug for Nanos {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
let d = Duration::from_nanos(self.0);
write!(f, "Nanos({d:?})")
}
}
// Add and Mul saturate: release builds disable overflow checks, and a wrapped
// TAT would admit every request; pinning at the far future denies instead.
impl Add<Self> for Nanos {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0.saturating_add(rhs.0))View on GitHub (pinned to 18893faf8b)
Solutions
- Clamp or validate the Duration before conversion (as_nanos() <= u64::MAX).
- Fix the unit conversion at the source of the Duration.
- Represent 'unlimited/never' with the library's dedicated constructs rather than a giant Duration.
Example fix
// before let nanos: Nanos = my_duration.into(); // panics for > 584 years // after assert!(my_duration.as_nanos() <= u64::MAX as u128, "duration exceeds Nanos range"); let nanos: Nanos = my_duration.into();
Defensive patterns
Strategy: validation
Validate before calling
fn to_nanos_safe(d: Duration) -> Option<u64> {
u64::try_from(d.as_nanos()).ok()
} Type guard
fn fits_nanos(d: &Duration) -> bool { d.as_nanos() <= u64::MAX as u128 } Try / catch
let result = std::panic::catch_unwind(|| { let n: Nanos = d.into(); n }); Prevention
- Validate durations from config before converting to Nanos
- Use explicit u64::try_from(as_nanos()) to get an error instead of a panic
- Audit unit handling when building Durations from user config
When it happens
Trigger: Converting a Duration into Nanos via .into()/From where d.as_nanos() > u64::MAX — e.g. building a Quota with an astronomically large replenish interval, or passing a bad Duration into rate limiter APIs.
Common situations: Configuration mistakes like a period parsed in the wrong unit (seconds value fed as nanoseconds), computed intervals from overflowing arithmetic, or Duration::MAX used as 'never'.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- Cannot represent durations greater than 584 years
- DurationNanos overflow in from_micros
- {e}
- `durations_seconds` value is too large, was {value}
- {field} exceeds the maximum backoff duration
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/76e263feda2911db.
Report an issue: GitHub.