nautechsystems/nautilus_trader · error
year arithmetic overflow
Error message
year arithmetic overflow
What it means
In the forward year walk, checked_add(step_i32) computes the next candidate year; if the addition overflows i32 the expect panics. With a sane positive step the break condition fires long before i32 overflow, so this signals an extreme step value or pathological input year.
Source
Thrown at crates/model/src/data/bar.rs:312
Date::new(year, 1, 1)
.expect("valid year start date")
.at(0, 0, 0, 0),
)
.expect("valid UTC year start")
+ origin_offset
};
let mut year = i32::from(Offset::UTC.to_datetime(now).year());
if year_start(year) > now {
year = year
.checked_sub(step_i32)
.expect("year arithmetic underflow");
}
loop {
let next_year = year
.checked_add(step_i32)
.expect("year arithmetic overflow");
if year_start(next_year) > now {
break;
}
year = next_year;
}
year_start(year)
}
_ => panic!(
"Aggregation type {} not supported for time bars",
spec.aggregation
),
}
}
/// Finds the closest smaller time based on a daily time origin and period.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Set a realistic Year step (small positive integer) in the bar spec.
- Validate 0 < step and now_year + step <= i32::MAX (practically <= ~9000 for jiff) before constructing the BarType.
- Reject invalid bar specs at configuration load rather than at runtime.
- Report a bug if overflow occurs with a plausible step.
Example fix
// before let bar_type = BarType::from_spec(2_000_000_000, BarAggregation::Year); // after let step = 2_000_000_000.min(9_000); // clamp or reject absurd steps assert!(step > 0); let bar_type = BarType::from_spec(step, BarAggregation::Year);
Defensive patterns
Strategy: validation
Validate before calling
let step = step_to_i64(spec.step);
let now_year = i64::from(Offset::UTC.to_datetime(now).year());
if step <= 0 || now_year + step > 9_000 {
return Err(format!("year step {step} would overflow the year walk"));
} Type guard
fn year_walk_safe(now_year: i32, step: i64) -> bool {
step > 0 && now_year as i64 + step <= 9_000
} Try / catch
let start = std::panic::catch_unwind(|| get_time_bar_start(now, &bar_type, origin))
.map_err(|_| anyhow::anyhow!("year arithmetic overflow"))?; Prevention
- Validate Year bar specs (small positive steps) before registering timers.
- Reject huge step values at strategy-config load time.
- Cover Year aggregation boundary behavior in unit tests.
When it happens
Trigger: get_time_bar_start with a Year bar where repeatedly adding step_i32 to `year` exceeds i32::MAX before year_start(next_year) > now — requires a step near i32::MAX (near the earlier i32 conversion limit) plus an in-range `now`.
Common situations: Misconfigured Year bar specs with billion-year steps from unit confusion; programmatic spec generation without validation; range-probing 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
- `step` overflows i64 days
- `step` exceeds u32 range for month arithmetic
- `step` exceeds i32 range for year arithmetic
- year arithmetic underflow
- DurationNanos overflow in from_millis
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/19ac712e2d9417d9.
Report an issue: GitHub.