nautechsystems/nautilus_trader · error
UnixNanos overflow in from_micros
Error message
UnixNanos overflow in from_micros
What it means
`UnixNanos::from_micros` converts a microsecond timestamp to nanoseconds using `checked_mul(NANOSECONDS_IN_MICROSECOND)` and panics on u64 overflow. Overflow means the microsecond value exceeds about 18,446,744,073,709,551 microseconds since epoch, outside the representable UnixNanos range.
Source
Thrown at crates/core/src/nanos.rs:464
/// Creates a new [`UnixNanos`] from a signed millisecond timestamp.
///
/// Returns `None` if `millis` is negative or the result overflows `u64`.
#[must_use]
pub const fn from_millis_checked(millis: i64) -> Option<Self> {
Self::from_units_checked(millis, NANOSECONDS_IN_MILLISECOND)
}
/// Creates a new [`UnixNanos`] from a microsecond timestamp.
///
/// # Panics
///
/// Panics if the result overflows `u64`.
#[must_use]
pub const fn from_micros(micros: u64) -> Self {
match micros.checked_mul(NANOSECONDS_IN_MICROSECOND) {
Some(nanos) => Self(nanos),
None => panic!("UnixNanos overflow in from_micros"),
}
}
/// Creates a new [`UnixNanos`] from a signed microsecond timestamp.
///
/// Returns `None` if `micros` is negative or the result overflows `u64`.
#[must_use]
pub const fn from_micros_checked(micros: i64) -> Option<Self> {
Self::from_units_checked(micros, NANOSECONDS_IN_MICROSECOND)
}
const fn from_units_checked(value: i64, nanos_per_unit: u64) -> Option<Self> {
if value < 0 {
return None;
}
match value.cast_unsigned().checked_mul(nanos_per_unit) {
Some(nanos) => Some(Self(nanos)),View on GitHub (pinned to 18893faf8b)
Solutions
- Confirm the input precision and pick the matching constructor (from_millis, from_seconds, or direct `UnixNanos::new` for nanos).
- Validate `micros <= u64::MAX / 1_000` before the call.
- Use a checked path (`micros.checked_mul(1_000)`) and handle None gracefully.
- Clamp or reject out-of-range timestamps at the data-ingestion boundary.
Example fix
// before
let ts = UnixNanos::from_micros(event_ts_us);
// after
let ts = match event_ts_us.checked_mul(1_000) {
Some(n) => UnixNanos::new(n),
None => return Err(anyhow!("event_ts_us out of UnixNanos range")),
}; Defensive patterns
Strategy: validation
Validate before calling
const MAX_UNIXNANOS_MICROS: u64 = u64::MAX / 1_000;
fn valid_epoch_micros(u: u64) -> bool { u <= MAX_UNIXNANOS_MICROS } Type guard
fn unix_nanos_from_micros(u: u64) -> Option<UnixNanos> {
u.checked_mul(1_000).map(UnixNanos::new)
} Prevention
- Verify microsecond precision at the data source; telemetry often emits nanos.
- Bound-check microsecond timestamps before conversion.
- Fall back to the Option-returning checked path for external inputs.
When it happens
Trigger: Calling `UnixNanos::from_micros(u)` with `u > 18_446_744_073_709` (u64::MAX / 1e3), so checked_mul returns None and the panic fires.
Common situations: Unit confusion: passing nanosecond or millisecond values into from_micros; timestamps from external systems (e.g. telemetry) in different precision; sentinel max-u64 values meaning 'infinite expiry'.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- UnixNanos overflow in from_seconds
- UnixNanos overflow in from_millis
- DurationNanos overflow in from_millis
- DurationNanos overflow in from_secs
- DurationNanos overflow in from_mins
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/795ae82b97307c1e.
Report an issue: GitHub.