{"record":{"id":"77c802ee48034e6e","repo":"nautechsystems/nautilus_trader","slug":"unixnanos-overflow-in-from-millis","errorCode":null,"errorMessage":"UnixNanos overflow in from_millis","messagePattern":"UnixNanos overflow in from_millis","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/core/src/nanos.rs","lineNumber":443,"sourceCode":"    /// Panics if the result overflows `u64`.\n    #[must_use]\n    pub const fn from_seconds(seconds: u64) -> Self {\n        match seconds.checked_mul(NANOSECONDS_IN_SECOND) {\n            Some(nanos) => Self(nanos),\n            None => panic!(\"UnixNanos overflow in from_seconds\"),\n        }\n    }\n\n    /// Creates a new [`UnixNanos`] from a millisecond timestamp.\n    ///\n    /// # Panics\n    ///\n    /// Panics if the result overflows `u64`.\n    #[must_use]\n    pub const fn from_millis(millis: u64) -> Self {\n        match millis.checked_mul(NANOSECONDS_IN_MILLISECOND) {\n            Some(nanos) => Self(nanos),\n            None => panic!(\"UnixNanos overflow in from_millis\"),\n        }\n    }\n\n    /// Creates a new [`UnixNanos`] from a signed millisecond timestamp.\n    ///\n    /// Returns `None` if `millis` is negative or the result overflows `u64`.\n    #[must_use]\n    pub const fn from_millis_checked(millis: i64) -> Option<Self> {\n        Self::from_units_checked(millis, NANOSECONDS_IN_MILLISECOND)\n    }\n\n    /// Creates a new [`UnixNanos`] from a microsecond timestamp.\n    ///\n    /// # Panics\n    ///\n    /// Panics if the result overflows `u64`.\n    #[must_use]\n    pub const fn from_micros(micros: u64) -> Self {","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/core/src/nanos.rs#L425-L461","documentation":"`UnixNanos::from_millis` converts a millisecond timestamp to nanoseconds via `checked_mul(NANOSECONDS_IN_MILLISECOND)` and panics when the result exceeds u64::MAX. The panic signals that the given millisecond value cannot be represented as UnixNanos; a non-panicking signed variant (`from_millis` on i64 returning Option) exists for error handling.","triggerScenarios":"Calling `UnixNanos::from_millis(m)` with `m > 18_446_744_073_709` (u64::MAX / 1e6), making the checked multiplication fail and the panic arm run.","commonSituations":"Feeding an already-nanosecond timestamp into from_millis (double conversion), producing a huge number; timestamps parsed from log lines or broker messages with wrong units; u64::MAX sentinel values for 'never expires'.","solutions":["Check the unit: if the value is already nanoseconds, construct directly with `UnixNanos::new(value)` instead of multiplying again.","Bound-check `millis <= u64::MAX / 1_000_000` before calling.","Use the signed/fallible variant that returns Option and handle None.","Reject implausible timestamps (far beyond current epoch time) during input validation."],"exampleFix":"// before\nlet ts = UnixNanos::from_millis(raw_ts); // raw_ts already in nanos\n\n// after\nlet ts = UnixNanos::new(raw_ts); // no unit conversion needed","handlingStrategy":"validation","validationCode":"const MAX_UNIXNANOS_MILLIS: u64 = u64::MAX / 1_000_000;\nfn valid_epoch_millis(m: u64) -> bool { m <= MAX_UNIXNANOS_MILLIS }","typeGuard":"fn unix_nanos_from_millis(m: u64) -> Option<UnixNanos> {\n    m.checked_mul(1_000_000).map(UnixNanos::new)\n}","tryCatchPattern":null,"preventionTips":["If values already exceed ~1.8e13 they are probably nanoseconds already; construct directly with UnixNanos::new.","Validate timestamp plausibility (near current epoch) before conversion.","Centralize unit conversion in one typed helper per unit."],"tags":["rust","panic","integer-overflow","timestamp","unix-nanos"],"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"}