nautechsystems/nautilus_trader · error · anyhow::Error
invalid negative Binance {field} timestamp: {value}
Error message
invalid negative Binance {field} timestamp: {value} What it means
Binance timestamps are converted to UnixNanos via checked constructors; a negative i64 cannot be represented as pre-epoch nanos in this domain type and is rejected. Binance commonly uses -1 as a 'not available' sentinel, which some fields legitimately carry and this strict parse refuses.
Source
Thrown at crates/adapters/binance/src/common/parse.rs:90
const CONTRACT_TYPE_CURRENT_QUARTER: &str = "CURRENT_QUARTER";
const CONTRACT_TYPE_NEXT_QUARTER: &str = "NEXT_QUARTER";
pub(crate) fn parse_millis(value: i64, field: &str) -> anyhow::Result<UnixNanos> {
parse_timestamp(value, UnixNanos::from_millis_checked(value), field)
}
pub(crate) fn parse_micros(value: i64, field: &str) -> anyhow::Result<UnixNanos> {
parse_timestamp(value, UnixNanos::from_micros_checked(value), field)
}
fn parse_timestamp(
value: i64,
timestamp: Option<UnixNanos>,
field: &str,
) -> anyhow::Result<UnixNanos> {
timestamp.ok_or_else(|| {
if value < 0 {
anyhow::anyhow!("invalid negative Binance {field} timestamp: {value}")
} else {
anyhow::anyhow!("Binance {field} timestamp is outside the UnixNanos range: {value}")
}
})
}
pub(crate) fn parse_millis_or_init(value: i64, field: &str, ts_init: UnixNanos) -> UnixNanos {
timestamp_or_init(parse_millis(value, field), ts_init)
}
pub(crate) fn parse_micros_or_init(value: i64, field: &str, ts_init: UnixNanos) -> UnixNanos {
timestamp_or_init(parse_micros(value, field), ts_init)
}
fn timestamp_or_init(timestamp: anyhow::Result<UnixNanos>, ts_init: UnixNanos) -> UnixNanos {
match timestamp {
Ok(timestamp) => timestamp,
Err(e) => {View on GitHub (pinned to a4b06ed870)
Solutions
- Identify the offending field from the {field} placeholder, then inspect the raw Binance payload - -1 means 'absent', not a valid time
- Update the adapter to a version handling the sentinel for that field, or report the field to maintainers
- If replaying old captures, regenerate/normalize them so absent times are omitted rather than -1
Example fix
// before: strict parse of a sentinel-carrying field
let ts = parse_millis(raw_time, "eventTime")?;
// after: treat the -1 sentinel as absent
let ts = if raw_time < 0 { fallback_ts } else { parse_millis(raw_time, "eventTime")? }; Defensive patterns
Strategy: type-guard
Validate before calling
fn is_representable_timestamp(value: i64) -> bool {
value >= 0
} Type guard
fn is_non_negative_timestamp(value: i64) -> bool {
value >= 0
} Try / catch
let ts = parse_millis(value, field).unwrap_or_else(|e| {
log::warn!("invalid {field} timestamp {value} ({e}) - using event ts_init fallback");
ts_init
}); Prevention
- When replaying captured Binance data, normalize -1 sentinel times to absent
- Log the field name and raw value on timestamp parse failures to spot schema drift early
- Validate third-party data feeds for sentinel usage before piping them into the adapter
When it happens
Trigger: A REST/stream payload contains a negative value (typically -1) in a timestamp field the adapter parses strictly via parse_millis/parse_micros - e.g. an optional event time absent for a newly listed or partially populated instrument.
Common situations: Replaying captured data whose sentinel fields were not normalized; a Binance endpoint starting to populate an optional time with -1; upstream schema drift on specific symbols.
Related errors
- Binance {field} timestamp is outside the UnixNanos range: {v
- {standard_key_var} not found in config or environment
- {standard_secret_var} not found in config or environment
- missing broker client order ID signal
- invalid O-format broker client order ID payload length
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/7b3f24927b0a5392.
Report an issue: GitHub.