{"record":{"id":"6120e1056505ff37","repo":"nautechsystems/nautilus_trader","slug":"seconds-secs-is-out-of-range-for-u64-milliseco","errorCode":null,"errorMessage":"seconds {secs} is out of range for `u64` milliseconds","messagePattern":"seconds (.+?) is out of range for `u64` milliseconds","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/core/src/datetime.rs","lineNumber":260,"sourceCode":"\n/// Converts seconds to milliseconds (ms).\n///\n/// # Errors\n///\n/// Returns an error if `secs` is non-finite or cannot be represented as `u64` milliseconds.\n#[expect(\n    clippy::cast_possible_truncation,\n    clippy::cast_sign_loss,\n    clippy::cast_precision_loss,\n    reason = \"Intentional for unit conversion, may lose precision after clamping\"\n)]\npub fn secs_to_millis(secs: f64) -> anyhow::Result<u64> {\n    anyhow::ensure!(secs.is_finite(), \"seconds must be finite, was {secs}\");\n    if secs <= 0.0 {\n        return Ok(0);\n    }\n    let millis = secs * MILLISECONDS_IN_SECOND as f64;\n    anyhow::ensure!(\n        millis < U64_UPPER_BOUND_F64,\n        \"seconds {secs} is out of range for `u64` milliseconds\"\n    );\n    Ok(millis.trunc() as u64)\n}\n\n/// Converts seconds to nanoseconds (ns), panicking on invalid input.\n///\n/// This is a convenience wrapper around [`secs_to_nanos`] when the caller expects\n/// the input to be trusted and in-range.\n///\n/// # Panics\n///\n/// Panics if [`secs_to_nanos`] would return an error for `secs`.\n#[must_use]\npub fn secs_to_nanos_unchecked(secs: f64) -> u64 {\n    secs_to_nanos(secs).expect(\"secs_to_nanos_unchecked: invalid or overflowing input\")\n}","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/core/src/datetime.rs#L242-L278","documentation":"secs_to_millis stores the result in u64, which caps at ~1.8446744e19 milliseconds (about 5.8e8 years). This error means the input seconds exceed that range after conversion, so the conversion would overflow.","triggerScenarios":"Calling secs_to_millis with secs where secs * 1e3 >= U64_UPPER_BOUND_F64 (secs >= ~1.8446744e16 seconds).","commonSituations":"Unit confusion — passing nanosecond or microsecond counts as seconds; parsing an unvalidated numeric field from config or a wire payload that contains an absurd value.","solutions":["Verify the input unit; convert (divide) if the value is in ms/us/ns not seconds.","Range-check the seconds value before conversion and reject/clamp implausible values.","Validate the source data (config/JSON) with an explicit upper bound."],"exampleFix":"// before\nlet ms = secs_to_millis(nano_value as f64)?; // overflow\n// after\nlet ms = secs_to_millis(nano_value as f64 / 1_000_000_000.0)?;","handlingStrategy":"validation","validationCode":"const MAX_SECS_F64: f64 = 1.8446744e16; // u64::MAX milliseconds in seconds\nif !secs.is_finite() || secs < 0.0 || secs >= MAX_SECS_F64 {\n    return Err(format!(\"seconds out of convertible range: {secs}\"));\n}","typeGuard":"fn is_convertible_secs(x: f64) -> bool { x.is_finite() && x > 0.0 && x < 1.8446744e16 }","tryCatchPattern":"let ms = match secs_to_millis(secs) {\n    Ok(ms) => ms,\n    Err(e) if e.to_string().contains(\"out of range\") => u64::MAX, // or bail with a unit check\n    Err(e) => return Err(e),\n};","preventionTips":["Check units before calling; ms/us/ns values passed as seconds overflow easily.","Clamp or bound-check numeric config values at parse time.","Prefer integer time types end-to-end to avoid f64 conversion entirely."],"tags":["rust","datetime","overflow","unit-conversion"],"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"}