{"record":{"id":"2bee8ba79fbff2cf","repo":"nautechsystems/nautilus_trader","slug":"year-exceeds-jiff-supported-range","errorCode":null,"errorMessage":"year exceeds Jiff supported range","messagePattern":"year exceeds Jiff supported range","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/bar.rs","lineNumber":291,"sourceCode":"            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\n                    .to_timestamp(\n                        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 {","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/bar.rs#L273-L309","documentation":"Inside the Year branch, each candidate year is narrowed from i32 to i16 because jiff's civil Date only supports years in roughly -9999..9999. When the candidate year leaves that range (after stepping by step_i32), try_from fails and the expect panics. It marks that the year walk ran past the calendar library's supported range.","triggerScenarios":"get_time_bar_start with a Year bar where year ± step_i32 walks beyond jiff's supported year range — e.g. current year plus a step like 2_000_000_000, or checked_add accumulating past i16 bounds before the break condition is met.","commonSituations":"Absurdly large Year steps from misconfigured specs; unchecked programmatic BarType construction; tests probing range limits.","solutions":["Use a realistic Year step (e.g. 1-1000 years) in the bar spec.","Validate that now_year + step stays within jiff's supported range before registering the timer.","Bound step so step <= ~9000 to guarantee the walk stays in range.","Switch aggregation (Day/Month) if an enormous period is intended."],"exampleFix":"// before\nBarType::from_spec(2_000_000_000, BarAggregation::Year)\n// after\nassert!(step > 0 && step <= 9_000);\nBarType::from_spec(step, BarAggregation::Year)","handlingStrategy":"validation","validationCode":"let now_year = Offset::UTC.to_datetime(now).year();\nif now_year.abs() + step > 9_000 {\n    return Err(format!(\"year step {step} pushes beyond supported calendar range\"));\n}","typeGuard":"fn year_step_in_range(now_year: i16, step: i64) -> bool {\n    (now_year as i64).abs() + 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 walk exceeded jiff supported range\"))?;","preventionTips":["Keep Year steps small enough that current_year + step stays within jiff's range.","Validate at config load: reject Year bars with step > ~9000.","Prefer Day/Month aggregation for very long periods."],"tags":["rust","panic","integer-overflow","date-range"],"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-14T00:17:10.932Z"}