nautechsystems/nautilus_trader · error
{field} must be non-negative, was {value}
Error message
{field} must be non-negative, was {value} What it means
Field sanity guard parse_millis_i64 used across Bybit WebSocket parsing: venue timestamps must be non-negative; a negative millis value indicates a malformed message and is rejected before conversion to UnixNanos.
Source
Thrown at crates/adapters/bybit/src/websocket/parse.rs:676
delta,
gamma,
vega,
theta,
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,View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the raw WebSocket payload and the field named in the error for the negative value
- Treat -1/unknown sentinels as absent and skip or substitute a local receive timestamp
- Check for clock-skew arithmetic that subtracts a larger timestamp from a smaller one before calling the parser
Example fix
// before: passes sentinel straight through
let ts = parse_millis_i64(raw.ts, "ts")?;
// after: filter sentinels first
let ts = if raw.ts < 0 { recv_time_ns } else { parse_millis_i64(raw.ts, "ts")? }; Defensive patterns
Strategy: validation
Validate before calling
def valid_millis(v: int) -> bool:
return v >= 0 Type guard
def is_non_negative(v) -> bool:
return isinstance(v, int) and v >= 0 Try / catch
match parse_millis_i64(raw.ts, "ts") {
Err(e) if e.to_string().contains("must be non-negative") => use_recv_time_fallback(),
other => other?,
} Prevention
- Treat negative/sentinel timestamps as missing upstream
- Sanity-check derived timestamps for clock skew
- Validate timestamps at the message-decode boundary
When it happens
Trigger: Any WebSocket message (orderbook, trade tick, quote, orderbook deltas) carrying a negative millisecond timestamp field (e.g. `ts`, `transaction_time`) passed through parse_millis_i64.
Common situations: Clock skew producing negative derived deltas; upstream sending sentinel values like -1 for 'unknown'; corrupted or synthetic test payloads with negative times.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- millisecond timestamp overflowed
- Not a subscription channel: {kind}
- funding_interval_hour out of bounds
- Missing server timestamp (us_out) in response
- Execution timestamp '{time_str}' was before Unix epoch
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7b1ff348072b0d6c.
Report an issue: GitHub.