{"record":{"id":"60fb0307922ef59d","repo":"nautechsystems/nautilus_trader","slug":"step-exceeds-u32-range-for-month-arithmetic","errorCode":null,"errorMessage":"`step` exceeds u32 range for month arithmetic","messagePattern":"`step` exceeds u32 range for month arithmetic","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/bar.rs","lineNumber":274,"sourceCode":"        BarAggregation::Month => {\n            // Set to the first day of the year\n            let now_civil = Offset::UTC.to_datetime(now);\n            let mut start_time = Offset::UTC\n                .to_timestamp(\n                    Date::new(now_civil.year(), 1, 1)\n                        .expect(\"valid year start date\")\n                        .at(0, 0, 0, 0),\n                )\n                .expect(\"valid UTC year start\");\n            start_time += origin_offset;\n\n            if now < start_time {\n                start_time =\n                    subtract_n_months(start_time, 12).expect(\"Failed to subtract 12 months\");\n            }\n\n            let months_step =\n                u32::try_from(step).expect(\"`step` exceeds u32 range for month arithmetic\");\n\n            while start_time <= now {\n                start_time =\n                    add_n_months(start_time, months_step).expect(\"Failed to add months in loop\");\n            }\n\n            start_time =\n                subtract_n_months(start_time, months_step).expect(\"Failed to subtract months_step\");\n            start_time\n        }\n        BarAggregation::Year => {\n            let step_i32 =\n                i32::try_from(step).expect(\"`step` exceeds i32 range for year arithmetic\");\n\n            // Reconstruct from Jan 1 + origin each time to avoid leap-day drift\n            let year_start = |year: i32| {\n                let year = i16::try_from(year).expect(\"year exceeds Jiff supported range\");\n                Offset::UTC","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/bar.rs#L256-L292","documentation":"For Month bars, the aggregation step (an i64) is converted to u32 because add_n_months/subtract_n_months take u32 month counts. If the bar spec's step is negative or exceeds u32::MAX, try_from fails and the expect panics. The function documents this: `step` must be representable for the calendar arithmetic.","triggerScenarios":"Registering or computing a time bar with BarAggregation::Month and a step value > 4,294,967,295 months (e.g. step_to_i64 of a huge spec step) or a negative step reaching this branch.","commonSituations":"Typo or unit mistake in a bar spec (e.g. passing nanoseconds as the month step); programmatically generated BarType specs with unchecked step values; adversarial or corrupted configuration where the step field holds a raw byte value.","solutions":["Correct the bar spec step to the intended number of months (a small positive integer).","Validate step <= u32::MAX before constructing/registering the Month bar type.","Guard the call: check spec.aggregation and spec.step bounds before calling get_time_bar_start.","Use a Year aggregation instead if the intended period is many months."],"exampleFix":"// before\nBarType::from_spec(step: 5_000_000_000, BarAggregation::Month)\n// after\nassert!(step > 0 && step <= u32::MAX as i64);\nBarType::from_spec(step, BarAggregation::Month)","handlingStrategy":"validation","validationCode":"fn validate_month_step(spec: &BarSpec) -> Result<(), String> {\n    if spec.aggregation != BarAggregation::Month { return Ok(()); }\n    let step = step_to_i64(spec.step);\n    if step <= 0 { return Err(\"month step must be positive\".into()); }\n    if step > u32::MAX as i64 { return Err(\"month step exceeds u32 range\".into()); }\n    Ok(())\n}","typeGuard":"fn valid_month_step(step: i64) -> bool { step > 0 && step <= u32::MAX as i64 }","tryCatchPattern":"let start = std::panic::catch_unwind(|| get_time_bar_start(now, &bar_type, origin))\n    .map_err(|_| anyhow::anyhow!(\"invalid month step for {bar_type}\"))?;","preventionTips":["Validate BarType steps at configuration parse time, not at timer registration.","Watch for unit confusion (nanoseconds vs months) when building specs programmatically.","Add round-trip tests for every bar spec loaded from config."],"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"}