{"record":{"id":"f10d5091dec1e820","repo":"nautechsystems/nautilus_trader","slug":"days-overflow-i64-hours","errorCode":null,"errorMessage":"days overflow i64 hours","messagePattern":"days overflow i64 hours","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/bar.rs","lineNumber":362,"sourceCode":"    let time_difference = base_time.duration_until(now);\n    let period_ns = period.as_nanos();\n    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)?,","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/bar.rs#L344-L380","documentation":"try_duration_days converts a day count into a SignedDuration by first computing days × 24 hours in checked i64 arithmetic. If days is so large that days × 24 exceeds i64 range, this error is thrown rather than silently wrapping. The public duration_days panics on it, so it typically surfaces as a panic in unwrapping paths.","triggerScenarios":"Calling duration_days/try_scaled_days with an i64 day value greater than i64::MAX / 24 (≈ 385 quadrillion days) — effectively only with absurd or corrupted values.","commonSituations":"Corrupted configuration of bar aggregation intervals; unit tests probing overflow behavior; a usize step converted from user input that was never bounded.","solutions":["Bound the days value to a realistic maximum before conversion","Use try_duration_days and handle the error instead of duration_days' unwrap/panic","Validate user/config-supplied intervals up front"],"exampleFix":"// before\nlet dur = duration_days(days); // panics on overflow\n// after\nlet dur = try_duration_days(days).unwrap_or_else(|_| SignedDuration::from_hours(i64::MAX)); // or handle Err","handlingStrategy":"try-catch","validationCode":"if days.abs() > i64::MAX / 24 { bail!(\"days too large\"); }","typeGuard":null,"tryCatchPattern":"match try_duration_days(days) {\n    Ok(d) => d,\n    Err(e) => { log::warn!(\"{e}\"); SignedDuration::ZERO }\n}","preventionTips":["Use try_duration_days rather than the panicking duration_days wrapper","Bound configured day intervals to realistic values","Validate user input before converting to durations"],"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"}