nautechsystems/nautilus_trader · error
AX timestamp must be non-negative, was
Error message
AX timestamp must be non-negative, was {seconds} What it means
ax_timestamp_s_to_unix_nanos converts AX epoch-seconds (i64) to UnixNanos (u64). Negative seconds indicate malformed data from the AX feed, so the function errors via anyhow::ensure before the cast. This protects the unsigned UnixNanos type from wrap-around.
Solutions
- Inspect the raw AX message to find why the timestamp is negative (field shift, sentinel value)
- Skip or drop the malformed report and log the offending message
- Sanitize/negotiate upstream data; if sentinel -1 is expected, filter it before conversion
Example fix
// before
let ts = ax_timestamp_s_to_unix_nanos(report.ts)?;
// after
if report.ts < 0 { log::warn!("skipping report with negative ts"); return Ok(None); }
let ts = ax_timestamp_s_to_unix_nanos(report.ts)?; Defensive patterns
Strategy: validation
Validate before calling
// Rust
if seconds < 0 { /* skip message or substitute clock timestamp */ } Try / catch
// Rust
match ax_timestamp_s_to_unix_nanos(seconds) {
Ok(ts) => ts,
Err(e) => { log::warn!("malformed AX timestamp: {e}"); skip(); }
} Prevention
- Validate timestamp fields before conversion when consuming raw AX payloads
- Log raw messages with negative timestamps for upstream reporting
- Handle sentinel values like -1 explicitly before parsing
When it happens
Trigger: Calling ax_timestamp_s_to_unix_nanos with a negative i64, typically from parse_bar or parse_order_status_report_fields when AX sends a malformed/negative timestamp field.
Common situations: AX upstream sending corrupt or placeholder timestamps (e.g. -1 sentinels); misparsed fields shifting a signed value into the timestamp column; unit tests feeding negative values.
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
- AX timestamp_ns must be non-negative, was
- AX requires whole contract quantities, was
- Empty underlying for
- event_slug_builder offset resolves before the Unix epoch
- Execution timestamp ' ' was before Unix epoch
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/6333e93c9c0c3461.
Report an issue: GitHub.
Appendix: 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 18893faf8b)