nautechsystems/nautilus_trader · error · anyhow::Error

AX timestamp must be non-negative, was {seconds}

Error message

AX timestamp must be non-negative, was {seconds}

What it means

ax_timestamp_s_to_unix_nanos converts an ArchitectHUB epoch-seconds field to UnixNanos and guards against negative seconds, which would denote a pre-1970 timestamp. Architect timestamps are always post-epoch, so a negative value means malformed or garbage data from the venue/feed, and the adapter refuses to fabricate a time.

Source

Thrown at crates/adapters/architect_ax/src/common/parse.rs:46

};
use nautilus_model::{
    data::BarSpecification,
    enums::AggressorSide,
    identifiers::{ClientOrderId, TradeId},
    types::{Price, Quantity, fixed::FIXED_PRECISION, quantity::QuantityRaw},
};

use super::enums::AxCandleWidth;

const NANOSECONDS_IN_SECOND: u64 = 1_000_000_000;

/// Converts an AX epoch-seconds timestamp to [`UnixNanos`].
///
/// # Errors
///
/// Returns an error if `seconds` is negative (malformed data from AX).
pub fn ax_timestamp_s_to_unix_nanos(seconds: i64) -> anyhow::Result<UnixNanos> {
    anyhow::ensure!(
        seconds >= 0,
        "AX timestamp must be non-negative, was {seconds}"
    );
    Ok(UnixNanos::from(seconds as u64 * NANOSECONDS_IN_SECOND))
}

/// Converts AX `ts` (seconds) + `tn` (nanoseconds) fields to [`UnixNanos`].
///
/// # Errors
///
/// Returns an error if `seconds` is negative (malformed data from AX).
pub fn ax_timestamp_stn_to_unix_nanos(seconds: i64, nanos: i64) -> anyhow::Result<UnixNanos> {
    anyhow::ensure!(
        seconds >= 0,
        "AX timestamp must be non-negative, was {seconds}"
    );
    let nanos_part = nanos.max(0) as u64;
    Ok(UnixNanos::from(

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Capture the offending raw message and report it to the nautilus_trader maintainers with the timestamp
  2. If it comes from your own test fixtures, set non-negative epoch-seconds values
  3. Check for an architect_ax adapter version mismatch with the live API and upgrade
  4. Verify the feed account/environment is healthy (resync/reconnect) before suspecting local code

Example fix

// before (fixture)
let ts = ax_timestamp_s_to_unix_nanos(-1)?; // AX timestamp must be non-negative, was -1

// after
let ts = ax_timestamp_s_to_unix_nanos(1_700_000_000)?;
Defensive patterns

Strategy: try-catch

Type guard

fn is_valid_ax_seconds(seconds: i64) -> bool {
    (0..i64::MAX).contains(&seconds)
}

Try / catch

// Rust: adapter-level handling
match ax_timestamp_s_to_unix_nanos(ts) {
    Ok(nanos) => nanos,
    Err(e) => {
        tracing::error!("dropping malformed AX message: {e}");
        return Ok(()); // skip the corrupt message, keep the stream alive
    }
}

Prevention

When it happens

Trigger: An inbound AX WebSocket message whose ts/seconds field decodes to a negative i64 (corrupted frame, decoding offset bug, or a test fixture with an uninitialised value) reaching ax_timestamp_s_to_unix_nanos.

Common situations: Almost exclusively an adapter/data-feed defect: protocol changes on Architect's side, a buffer misparse after an API update, or hand-crafted fixture data using -1 as a sentinel. End users cannot trigger it with valid config.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/6333e93c9c0c3461. Report an issue: GitHub.