{"record":{"id":"2a3bdbd36ce09a19","repo":"nautechsystems/nautilus_trader","slug":"days-exceed-signed-duration-range","errorCode":null,"errorMessage":"days exceed signed duration range","messagePattern":"days exceed signed duration range","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/bar.rs","lineNumber":364,"sourceCode":"    debug_assert_ne!(period_ns, 0, \"bar period must be non-zero\");\n\n    // Use div_euclid for floor division (rounds toward -inf, not zero)\n    // so negative deltas (now before origin) yield the previous period boundary\n    let num_periods = time_difference.as_nanos().div_euclid(period_ns);\n\n    base_time + SignedDuration::from_nanos_i128(num_periods * period_ns)\n}\n\nfn duration_days(days: i64) -> SignedDuration {\n    try_duration_days(days).unwrap_or_else(|e| panic!(\"{e}\"))\n}\n\nfn try_duration_days(days: i64) -> anyhow::Result<SignedDuration> {\n    let hours = days\n        .checked_mul(24)\n        .ok_or_else(|| anyhow::anyhow!(\"days overflow i64 hours\"))?;\n    SignedDuration::try_from_hours(hours)\n        .ok_or_else(|| anyhow::anyhow!(\"days exceed signed duration range\"))\n}\n\nfn try_time_interval(step: usize, aggregation: BarAggregation) -> anyhow::Result<SignedDuration> {\n    let step_i64 = i64::try_from(step)\n        .map_err(|_| invalid_interval_step(step, aggregation, \"step exceeds i64 range\"))?;\n\n    let duration = match aggregation {\n        BarAggregation::Millisecond => SignedDuration::from_millis(step_i64),\n        BarAggregation::Second => SignedDuration::from_secs(step_i64),\n        BarAggregation::Minute => SignedDuration::try_from_mins(step_i64).ok_or_else(|| {\n            invalid_interval_step(step, aggregation, \"step exceeds signed duration range\")\n        })?,\n        BarAggregation::Hour => SignedDuration::try_from_hours(step_i64).ok_or_else(|| {\n            invalid_interval_step(step, aggregation, \"step exceeds signed duration range\")\n        })?,\n        BarAggregation::Day => try_scaled_days(step, aggregation, step_i64, 1)?,\n        BarAggregation::Week => try_scaled_days(step, aggregation, step_i64, 7)?,\n        BarAggregation::Month => try_scaled_days(step, aggregation, step_i64, 30)?,","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/bar.rs#L346-L382","documentation":"After days × 24 succeeds, the hour count is converted to a SignedDuration via try_from_hours, which has its own narrower representable range. If hours fits i64 but exceeds the SignedDuration range, this error is thrown. Like the overflow sibling, it propagates through callers that may panic via unwrap.","triggerScenarios":"Calling duration_days/try_scaled_days with days whose ×24 hour value is within i64 but outside SignedDuration::try_from_hours' accepted range (very large positive or negative day counts).","commonSituations":"Malformed or malicious interval configuration; tests probing duration limits; unbounded arithmetic on user-supplied aggregation steps.","solutions":["Clamp days to the SignedDuration-representable range before conversion","Handle the error from try_duration_days instead of panicking via duration_days","Validate configured bar intervals against known aggregation limits"],"exampleFix":"// before\nlet dur = duration_days(days);\n// after\nlet dur = match try_duration_days(days) { Ok(d) => d, Err(e) => { warn!(\"{e}\"); return Err(e); } };","handlingStrategy":"try-catch","validationCode":"if days.abs() > (i64::MAX / 86_400_000_000) { bail!(\"days outside SignedDuration range\"); }","typeGuard":null,"tryCatchPattern":"let dur = try_duration_days(days).unwrap_or_else(|e| { warn!(\"{e}\"); fallback_duration });","preventionTips":["Clamp day values to the SignedDuration range","Prefer the Result-returning API over panicking wrappers","Validate aggregation interval configuration at load time"],"tags":["rust","overflow","time-duration","bars"],"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"}