nautechsystems/nautilus_trader · error
millisecond timestamp overflowed
Error message
millisecond timestamp overflowed
What it means
parse_millis_i64 multiplies the millisecond value by 1,000,000 to obtain nanoseconds using checked arithmetic on u64. If the resulting nanosecond value exceeds u64 range, this overflow error is thrown.
Source
Thrown at crates/adapters/bybit/src/websocket/parse.rs:680
rho: 0.0, // Bybit doesn't provide rho
},
mark_iv: Some(mark_iv),
bid_iv: Some(bid_iv),
ask_iv: Some(ask_iv),
underlying_price: Some(underlying_price),
open_interest: Some(open_interest),
ts_event,
ts_init,
})
}
pub(crate) fn parse_millis_i64(value: i64, field: &str) -> anyhow::Result<UnixNanos> {
if value < 0 {
Err(anyhow::anyhow!("{field} must be non-negative, was {value}"))
} else {
let nanos = (value as u64)
.checked_mul(NANOSECONDS_IN_MILLISECOND)
.ok_or_else(|| anyhow::anyhow!("millisecond timestamp overflowed"))?;
Ok(UnixNanos::from(nanos))
}
}
/// Parses a WebSocket kline payload into a [`Bar`].
///
/// # Errors
///
/// Returns an error if price or volume fields cannot be parsed or if the bar cannot be constructed.
pub fn parse_ws_kline_bar(
kline: &BybitWsKline,
instrument: &InstrumentAny,
bar_type: BarType,
timestamp_on_close: bool,
ts_init: UnixNanos,
) -> anyhow::Result<Bar> {
let price_precision = instrument.price_precision();
let size_precision = instrument.size_precision();View on GitHub (pinned to 18893faf8b)
Solutions
- Log the raw value and verify its actual time unit against Bybit's API docs
- Convert with the correct unit multiplier if the field is actually microseconds/nanoseconds
- Add an upper-bound sanity check (e.g. reject timestamps far in the future) before conversion
Example fix
// before: assumes milliseconds, overflows on microsecond input let ts = parse_millis_i64(raw.ts, "ts")?; // after: correct unit for microsecond fields let ts = parse_micros_i64(raw.ts, "ts")?;
Defensive patterns
Strategy: validation
Validate before calling
def plausible_millis(v: int) -> bool:
return 0 <= v <= 4_102_444_800_000 # up to year 2100 Type guard
def is_plausible_timestamp(v) -> bool:
return isinstance(v, int) and 0 <= v <= 4_102_444_800_000 Try / catch
match parse_millis_i64(raw.ts, "ts") {
Err(e) if e.to_string().contains("overflowed") => { log_unit_mismatch(raw.ts); skip },
other => other?,
} Prevention
- Bound-check timestamps against a sane wall-clock window before conversion
- Confirm the time unit (ms vs us vs ns) after any Bybit API change
- Add fuzz/property tests with extreme timestamp values
When it happens
Trigger: A WebSocket payload (orderbook, trade tick, quote) carrying a millisecond timestamp larger than u64::MAX/1e6 (~1.8e13 ms, year ~539000) passed to parse_millis_i64.
Common situations: Upstream sending microseconds/nanoseconds mislabeled as milliseconds; unit-encoding schema changes; fabricated or fuzzed payloads with absurd timestamps.
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
- funding_interval_hour out of bounds
- {field} must be non-negative, was {value}
- Timestamp overflow for record
- Missing server timestamp (us_out) in response
- negative candle timestamp: {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/1e153b26027e8250.
Report an issue: GitHub.