nautechsystems/nautilus_trader · error
microsecond timestamp {micros} overflows when scaled to nano
Error message
microsecond timestamp {micros} overflows when scaled to nanoseconds What it means
parse_micros_to_nanos converts a microsecond timestamp to UnixNanos via micros.checked_mul(1_000). When that multiplication would overflow u64 the error is raised instead of allowing silent wraparound. Only values above u64::MAX / 1_000 (~1.8e16 microseconds) trigger it, far beyond any real timestamp.
Source
Thrown at crates/adapters/lighter/src/common/parse.rs:185
/// venue timestamps are nowhere near this bound; the check rejects malformed
/// payloads instead of silently wrapping in release builds.
pub fn parse_millis_to_nanos(millis: u64) -> anyhow::Result<UnixNanos> {
let nanos = millis
.checked_mul(NANOSECONDS_IN_MILLISECOND)
.ok_or_else(|| {
anyhow::anyhow!("millisecond timestamp {millis} overflows when scaled to nanoseconds")
})?;
Ok(UnixNanos::from(nanos))
}
/// Converts a Unix microsecond timestamp into [`UnixNanos`].
///
/// # Errors
///
/// Returns an error if `micros * 1_000` would overflow `u64`.
pub fn parse_micros_to_nanos(micros: u64) -> anyhow::Result<UnixNanos> {
let nanos = micros.checked_mul(1_000).ok_or_else(|| {
anyhow::anyhow!("microsecond timestamp {micros} overflows when scaled to nanoseconds")
})?;
Ok(UnixNanos::from(nanos))
}
/// Converts a Unix second timestamp into [`UnixNanos`].
///
/// # Errors
///
/// Returns an error if `secs * 1_000_000_000` would overflow `u64`.
pub fn parse_secs_to_nanos(secs: u64) -> anyhow::Result<UnixNanos> {
let nanos = secs.checked_mul(NANOSECONDS_IN_SECOND).ok_or_else(|| {
anyhow::anyhow!("second timestamp {secs} overflows when scaled to nanoseconds")
})?;
Ok(UnixNanos::from(nanos))
}
/// Converts a signed Unix millisecond timestamp into [`UnixNanos`].
///View on GitHub (pinned to 18893faf8b)
Solutions
- Confirm the timestamp unit; if the source value is already nanoseconds, use it directly without scaling.
- Validate/bound the incoming timestamp before conversion.
- For testing, keep values below u64::MAX / 1_000.
Example fix
// before let ts = parse_micros_to_nanos(nanos_value)?; // value is already nanos // after let ts = UnixNanos::from(nanos_value);
Defensive patterns
Strategy: validation
Validate before calling
fn micros_plausible(us: u64) -> bool { us < u64::MAX / 1_000 && us > 1_400_000_000_000_000 } Type guard
fn is_micros(v: u64) -> bool { (1_400_000_000_000_000..u64::MAX / 1_000).contains(&v) } Try / catch
match parse_micros_to_nanos(micros) {
Ok(ts) => ts,
Err(e) => { warn!("micros overflow: {e}"); UnixNanos::default() }
} Prevention
- Do not feed nanosecond values into the microsecond converter
- Bound-check microsecond timestamps before scaling
- Only real-time-scale values should ever reach this function
When it happens
Trigger: Calling parse_micros_to_nanos directly (its only caller is the test parse_micros_to_nanos_rejects_overflow) with micros > ~1.8e16, i.e. a corrupt or deliberately oversized value.
Common situations: Feeding nanosecond values into the microsecond converter; corrupted venue payloads; overflow unit tests.
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
- millisecond timestamp {millis} overflows when scaled to nano
- second timestamp {secs} overflows when scaled to nanoseconds
- Binance {field} timestamp is outside the UnixNanos range: {v
- Invalid execution time format: {time_str}
- Execution timestamp '{time_str}' is non-existent in timezone
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/2642f06e2420a23e.
Report an issue: GitHub.