nautechsystems/nautilus_trader · error
days overflow i64 hours
Error message
days overflow i64 hours
What it means
try_duration_days converts a day count into a SignedDuration by first computing days × 24 hours in checked i64 arithmetic. If days is so large that days × 24 exceeds i64 range, this error is thrown rather than silently wrapping. The public duration_days panics on it, so it typically surfaces as a panic in unwrapping paths.
Source
Thrown at crates/model/src/data/bar.rs:362
let time_difference = base_time.duration_until(now);
let period_ns = period.as_nanos();
debug_assert_ne!(period_ns, 0, "bar period must be non-zero");
// Use div_euclid for floor division (rounds toward -inf, not zero)
// so negative deltas (now before origin) yield the previous period boundary
let num_periods = time_difference.as_nanos().div_euclid(period_ns);
base_time + SignedDuration::from_nanos_i128(num_periods * period_ns)
}
fn duration_days(days: i64) -> SignedDuration {
try_duration_days(days).unwrap_or_else(|e| panic!("{e}"))
}
fn try_duration_days(days: i64) -> anyhow::Result<SignedDuration> {
let hours = days
.checked_mul(24)
.ok_or_else(|| anyhow::anyhow!("days overflow i64 hours"))?;
SignedDuration::try_from_hours(hours)
.ok_or_else(|| anyhow::anyhow!("days exceed signed duration range"))
}
fn try_time_interval(step: usize, aggregation: BarAggregation) -> anyhow::Result<SignedDuration> {
let step_i64 = i64::try_from(step)
.map_err(|_| invalid_interval_step(step, aggregation, "step exceeds i64 range"))?;
let duration = match aggregation {
BarAggregation::Millisecond => SignedDuration::from_millis(step_i64),
BarAggregation::Second => SignedDuration::from_secs(step_i64),
BarAggregation::Minute => SignedDuration::try_from_mins(step_i64).ok_or_else(|| {
invalid_interval_step(step, aggregation, "step exceeds signed duration range")
})?,
BarAggregation::Hour => SignedDuration::try_from_hours(step_i64).ok_or_else(|| {
invalid_interval_step(step, aggregation, "step exceeds signed duration range")
})?,
BarAggregation::Day => try_scaled_days(step, aggregation, step_i64, 1)?,View on GitHub (pinned to 18893faf8b)
Solutions
- Bound the days value to a realistic maximum before conversion
- Use try_duration_days and handle the error instead of duration_days' unwrap/panic
- Validate user/config-supplied intervals up front
Example fix
// before let dur = duration_days(days); // panics on overflow // after let dur = try_duration_days(days).unwrap_or_else(|_| SignedDuration::from_hours(i64::MAX)); // or handle Err
Defensive patterns
Strategy: try-catch
Validate before calling
if days.abs() > i64::MAX / 24 { bail!("days too large"); } Try / catch
match try_duration_days(days) {
Ok(d) => d,
Err(e) => { log::warn!("{e}"); SignedDuration::ZERO }
} Prevention
- Use try_duration_days rather than the panicking duration_days wrapper
- Bound configured day intervals to realistic values
- Validate user input before converting to durations
When it happens
Trigger: Calling duration_days/try_scaled_days with an i64 day value greater than i64::MAX / 24 (≈ 385 quadrillion days) — effectively only with absurd or corrupted values.
Common situations: Corrupted configuration of bar aggregation intervals; unit tests probing overflow behavior; a usize step converted from user input that was never bounded.
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
- days exceed signed duration range
- {e}
- Invalid step in bar_type.spec.step: {step} for aggregation={
- WETH balance overflow for included transaction {tx_hash} at
- DurationNanos overflow in from_micros
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f10d5091dec1e820.
Report an issue: GitHub.