{"record":{"id":"fd8d1049d30137c5","repo":"nautechsystems/nautilus_trader","slug":"milliseconds-millis-is-out-of-range-for-u64-na","errorCode":null,"errorMessage":"milliseconds {millis} is out of range for `u64` nanoseconds","messagePattern":"milliseconds (.+?) is out of range for `u64` nanoseconds","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/core/src/datetime.rs","lineNumber":320,"sourceCode":"///\n/// Returns an error if `millis` is non-finite or cannot be represented as `u64` nanoseconds.\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 millis_to_nanos(millis: f64) -> anyhow::Result<u64> {\n    anyhow::ensure!(\n        millis.is_finite(),\n        \"milliseconds must be finite, was {millis}\"\n    );\n\n    if millis <= 0.0 {\n        return Ok(0);\n    }\n    let nanos = millis * NANOSECONDS_IN_MILLISECOND as f64;\n    anyhow::ensure!(\n        nanos < U64_UPPER_BOUND_F64,\n        \"milliseconds {millis} is out of range for `u64` nanoseconds\"\n    );\n    Ok(nanos.trunc() as u64)\n}\n\n/// Converts milliseconds (ms) to nanoseconds (ns), panicking on invalid input.\n///\n/// # Panics\n///\n/// Panics if [`millis_to_nanos`] would return an error for `millis`.\n#[must_use]\npub fn millis_to_nanos_unchecked(millis: f64) -> u64 {\n    millis_to_nanos(millis).expect(\"millis_to_nanos_unchecked: invalid or overflowing input\")\n}\n\n/// Converts microseconds (μs) to nanoseconds (ns).\n///","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/core/src/datetime.rs#L302-L338","documentation":"millis_to_nanos multiplies by 1e6 and stores in u64, capped at ~1.8446744e19 nanoseconds (about 584 years, i.e. ~5.8e12 ms). This error means the input milliseconds exceed the u64 range after conversion.","triggerScenarios":"Calling millis_to_nanos with millis such that millis * 1e6 >= U64_UPPER_BOUND_F64 (millis >= ~1.8446744e13).","commonSituations":"Unit confusion — passing a nanosecond timestamp (1.7e18) as milliseconds; passing a raw UNIX millisecond timestamp where the API expects a duration; unvalidated numeric config values.","solutions":["Verify the input unit; if it is already nanoseconds, do not convert again.","Confirm whether the API expects a duration since epoch vs an offset; timestamps in ms since epoch (1.7e12) are fine, 1.7e15+ indicates a unit error.","Range-check the value before conversion and reject implausible durations."],"exampleFix":"// before\nlet ns = millis_to_nanos(ns_timestamp as f64)?; // double conversion\n// after\nlet ns = ns_timestamp; // already nanoseconds, no conversion needed","handlingStrategy":"validation","validationCode":"const MAX_MILLIS_F64: f64 = 1.8446744e13; // u64::MAX nanoseconds in milliseconds\nif !millis.is_finite() || millis < 0.0 || millis >= MAX_MILLIS_F64 {\n    return Err(format!(\"milliseconds out of convertible range: {millis}\"));\n}","typeGuard":"fn is_convertible_millis(x: f64) -> bool { x.is_finite() && x > 0.0 && x < 1.8446744e13 }","tryCatchPattern":"let ns = match millis_to_nanos(millis) {\n    Ok(ns) => ns,\n    Err(e) if e.to_string().contains(\"out of range\") => { log::error!(\"unit confusion? millis={millis}\"); bail!(e); }\n    Err(e) => return Err(e),\n};","preventionTips":["UNIX ms timestamps (~1.7e12) convert fine; values ~1.7e15+ indicate a unit error.","Do not double-convert: check whether the value is already nanoseconds.","Standardize the codebase on u64 nanoseconds to minimize conversions."],"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"}