nautechsystems/nautilus_trader · error
`step` exceeds i32 range for year arithmetic
Error message
`step` exceeds i32 range for year arithmetic
What it means
For Year bars, the step (i64) is narrowed to i32 for year arithmetic; if the value exceeds i32::MAX (or is negative), try_from fails and the expect panics. The function explicitly documents that `step` must be representable for the calendar arithmetic.
Source
Thrown at crates/model/src/data/bar.rs:287
start_time =
subtract_n_months(start_time, 12).expect("Failed to subtract 12 months");
}
let months_step =
u32::try_from(step).expect("`step` exceeds u32 range for month arithmetic");
while start_time <= now {
start_time =
add_n_months(start_time, months_step).expect("Failed to add months in loop");
}
start_time =
subtract_n_months(start_time, months_step).expect("Failed to subtract months_step");
start_time
}
BarAggregation::Year => {
let step_i32 =
i32::try_from(step).expect("`step` exceeds i32 range for year arithmetic");
// Reconstruct from Jan 1 + origin each time to avoid leap-day drift
let year_start = |year: i32| {
let year = i16::try_from(year).expect("year exceeds Jiff supported range");
Offset::UTC
.to_timestamp(
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)View on GitHub (pinned to 18893faf8b)
Solutions
- Fix the Year bar step to the intended small positive integer of years.
- Validate 0 < step <= i32::MAX before constructing the BarType.
- Reject such bar specs at configuration-parse time rather than at timer registration.
- If a huge period is genuinely needed, compose it via Month/Day aggregation instead.
Example fix
// before BarType::from_spec(10_000_000_000, BarAggregation::Year) // after assert!(step > 0 && step <= i32::MAX as i64); BarType::from_spec(step, BarAggregation::Year)
Defensive patterns
Strategy: validation
Validate before calling
fn validate_year_step(spec: &BarSpec) -> Result<(), String> {
if spec.aggregation != BarAggregation::Year { return Ok(()); }
let step = step_to_i64(spec.step);
if step <= 0 { return Err("year step must be positive".into()); }
if step > i32::MAX as i64 { return Err("year step exceeds i32 range".into()); }
Ok(())
} Type guard
fn valid_year_step(step: i64) -> bool { step > 0 && step <= i32::MAX as i64 } Try / catch
let start = std::panic::catch_unwind(|| get_time_bar_start(now, &bar_type, origin))
.map_err(|_| anyhow::anyhow!("invalid year step for {bar_type}"))?; Prevention
- Validate bar spec steps when loading strategy configuration.
- Reject absurd steps (years should be single/double digits in practice).
- Add unit tests for spec construction from raw config values.
When it happens
Trigger: get_time_bar_start (or start_timer_internal registering the timer) with BarAggregation::Year and a spec step > 2,147,483,647 years, or a negative step.
Common situations: Unit confusion when building the BarType spec (passing nanoseconds or seconds as the year step); programmatic spec generation without bounds checks; corrupted configuration files.
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
- year arithmetic underflow
- year arithmetic overflow
- DurationNanos overflow in from_millis
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/71c657f62a03aba2.
Report an issue: GitHub.