nautechsystems/nautilus_trader · error · anyhow::Error

invalid negative Binance

Error message

invalid negative Binance {field} timestamp: {value}

What it means

parse_timestamp converts an i64 epoch value into UnixNanos. When the parsed millis/micros value overflows or cannot be represented, it returns None, and this error is raised if that value was negative — a negative timestamp is semantically invalid for Binance fields.

Solutions

  1. Check the source JSON field for the negative value and fix the upstream data or fixture.
  2. Treat missing timestamps explicitly (e.g. use Option or parse_millis_or_init) instead of negative sentinels.
  3. Validate timestamps are >= 0 before passing them into the parser.
  4. Verify clock synchronization if timestamps are computed locally.

Example fix

// before
let ts = parse_millis(-1, "updateTime")?;

// after
let ts = if raw_update_time >= 0 {
    parse_millis(raw_update_time, "updateTime")?
} else {
    return Err(anyhow::anyhow!("updateTime missing from event"));
};
Defensive patterns

Strategy: validation

Validate before calling

fn is_plausible_ts(v: i64) -> bool { v >= 0 && v < 4_102_444_800_000 } // until year 2100, millis

Prevention

When it happens

Trigger: Calling parse_millis or parse_micros with a negative i64 from a Binance API field (e.g. time, updateTime, transactTime) — usually from corrupted data, mocked responses with -1 sentinels, or arithmetic producing negative epoch values.

Common situations: Test fixtures using -1 as a 'missing' sentinel; deserialization of corrupted responses; clock bugs producing negative derived timestamps; fields defaulting to negative values when absent.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/7b3f24927b0a5392. Report an issue: GitHub.

Appendix: 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 18893faf8b)