{"record":{"id":"19ac712e2d9417d9","repo":"nautechsystems/nautilus_trader","slug":"year-arithmetic-overflow","errorCode":null,"errorMessage":"year arithmetic overflow","messagePattern":"year arithmetic overflow","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/bar.rs","lineNumber":312,"sourceCode":"                        Date::new(year, 1, 1)\n                            .expect(\"valid year start date\")\n                            .at(0, 0, 0, 0),\n                    )\n                    .expect(\"valid UTC year start\")\n                    + origin_offset\n            };\n\n            let mut year = i32::from(Offset::UTC.to_datetime(now).year());\n            if year_start(year) > now {\n                year = year\n                    .checked_sub(step_i32)\n                    .expect(\"year arithmetic underflow\");\n            }\n\n            loop {\n                let next_year = year\n                    .checked_add(step_i32)\n                    .expect(\"year arithmetic overflow\");\n\n                if year_start(next_year) > now {\n                    break;\n                }\n                year = next_year;\n            }\n\n            year_start(year)\n        }\n        _ => panic!(\n            \"Aggregation type {} not supported for time bars\",\n            spec.aggregation\n        ),\n    }\n}\n\n/// Finds the closest smaller time based on a daily time origin and period.\n///","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/bar.rs#L294-L330","documentation":"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.","triggerScenarios":"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`.","commonSituations":"Misconfigured Year bar specs with billion-year steps from unit confusion; programmatic spec generation without validation; range-probing tests.","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."],"exampleFix":"// before\nlet bar_type = BarType::from_spec(2_000_000_000, BarAggregation::Year);\n// after\nlet step = 2_000_000_000.min(9_000); // clamp or reject absurd steps\nassert!(step > 0);\nlet bar_type = BarType::from_spec(step, BarAggregation::Year);","handlingStrategy":"validation","validationCode":"let step = step_to_i64(spec.step);\nlet now_year = i64::from(Offset::UTC.to_datetime(now).year());\nif step <= 0 || now_year + step > 9_000 {\n    return Err(format!(\"year step {step} would overflow the year walk\"));\n}","typeGuard":"fn year_walk_safe(now_year: i32, step: i64) -> bool {\n    step > 0 && now_year as i64 + step <= 9_000\n}","tryCatchPattern":"let start = std::panic::catch_unwind(|| get_time_bar_start(now, &bar_type, origin))\n    .map_err(|_| anyhow::anyhow!(\"year arithmetic overflow\"))?;","preventionTips":["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."],"tags":["rust","panic","integer-overflow","bar-aggregation"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}