{"record":{"id":"b2bd2e81d3fa5eef","repo":"nautechsystems/nautilus_trader","slug":"timestamp-out-of-range-for-trade","errorCode":null,"errorMessage":"Timestamp out of range for trade {}","messagePattern":"Timestamp out of range for trade (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/http/parse.rs","lineNumber":84,"sourceCode":"    trade: &Trade,\n    instrument_id: InstrumentId,\n    price_precision: u8,\n    size_precision: u8,\n    ts_init: UnixNanos,\n) -> anyhow::Result<TradeTick> {\n    let aggressor_side = match trade.side {\n        OrderSide::Buy => AggressorSide::Buy,\n        OrderSide::Sell => AggressorSide::Sell,\n    };\n\n    let price = Price::from_decimal_dp(trade.price, price_precision)\n        .context(format!(\"failed to parse price for trade {}\", trade.id))?;\n\n    let size = Quantity::from_decimal_dp(trade.size, size_precision)\n        .context(format!(\"failed to parse size for trade {}\", trade.id))?;\n\n    let ts_event_nanos = u64::try_from(trade.created_at.as_nanosecond())\n        .map_err(|_| anyhow::anyhow!(\"Timestamp out of range for trade {}\", trade.id))?;\n    let ts_event = UnixNanos::from(ts_event_nanos);\n\n    Ok(TradeTick::new(\n        instrument_id,\n        price,\n        size,\n        aggressor_side,\n        TradeId::new(&trade.id),\n        ts_event,\n        ts_init,\n    ))\n}\n\n/// Parses a dYdX [`Candle`] into a Nautilus [`Bar`].\n///\n/// When `timestamp_on_close` is true, `ts_event` is set to bar close time\n/// (started_at + interval). When false, uses the venue-native open time.\n///","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/http/parse.rs#L66-L102","documentation":"parse_trade_tick converts a trade's created_at timestamp into UnixNanos (u64). The error fires when u64::try_from fails because the timestamp is negative (before Unix epoch) or out of u64 nanosecond range, so the trade tick cannot be constructed.","triggerScenarios":"Parsing a dYdX trade whose created_at is negative or exceeds u64 nanoseconds, via parse_trade_tick (invoked from trade-tick requests).","commonSituations":"API returning a malformed or zeroed created_at; wrong datetime parsing producing pre-epoch values; upstream schema change in the trade feed; corrupted test fixture data (this symbol is exercised by test_parse_trade_tick).","solutions":["Log the offending trade payload (trade.id and raw created_at) to confirm the actual value","Fix the DateTime deserialization of created_at if the format/epoch assumption is wrong","Skip trades with out-of-range timestamps instead of failing the whole batch","Check for dYdX API version changes affecting the timestamp field"],"exampleFix":"// before\nlet ts_event_nanos = u64::try_from(trade.created_at.as_nanosecond())\n    .map_err(|_| anyhow::anyhow!(\"Timestamp out of range for trade {}\", trade.id))?;\n// after\nlet ts_event_nanos = u64::try_from(trade.created_at.as_nanosecond())\n    .map_err(|_| anyhow::anyhow!(\n        \"Timestamp out of range for trade {}: raw created_at={:?}\",\n        trade.id, trade.created_at\n    ))?;","handlingStrategy":"try-catch","validationCode":"if u64::try_from(trade.created_at.as_nanosecond()).is_err() {\n    log::warn!(\"trade {} has out-of-range created_at, skipping\", trade.id);\n    return Ok(None);\n}","typeGuard":"fn trade_timestamp_in_range(trade: &DydxTrade) -> bool {\n    u64::try_from(trade.created_at.as_nanosecond()).is_ok()\n}","tryCatchPattern":"match parse_trade_tick(trade, instrument, price_precision, size_precision) {\n    Ok(tick) => handle(tick),\n    Err(e) if e.to_string().contains(\"Timestamp out of range\") => {\n        log::warn!(\"skipping trade with bad timestamp: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Log raw created_at values when parsing fails to spot format drift","Validate timestamps at the HTTP deserialization layer, not at tick construction","Keep parse tests pinned to realistic dYdX trade fixtures"],"tags":["dydx","timestamp","parse","trade-tick"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}