{"record":{"id":"b4b26bd957ba24f3","repo":"nautechsystems/nautilus_trader","slug":"timestamp-out-of-range-for-candle-at","errorCode":null,"errorMessage":"Timestamp out of range for candle at {}","messagePattern":"Timestamp out of range for candle at (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/http/parse.rs","lineNumber":115,"sourceCode":"\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///\n/// # Errors\n///\n/// Returns an error if OHLCV or timestamp conversion fails.\npub fn parse_bar(\n    candle: &Candle,\n    bar_type: BarType,\n    price_precision: u8,\n    size_precision: u8,\n    timestamp_on_close: bool,\n    ts_init: UnixNanos,\n) -> anyhow::Result<Bar> {\n    let started_at_nanos = u64::try_from(candle.started_at.as_nanosecond()).map_err(|_| {\n        anyhow::anyhow!(\"Timestamp out of range for candle at {}\", candle.started_at)\n    })?;\n    let mut ts_event = UnixNanos::from(started_at_nanos);\n\n    if timestamp_on_close {\n        let interval_ns = bar_type.spec().timedelta().as_nanos();\n        let interval_ns =\n            u64::try_from(interval_ns).context(\"bar interval overflowed u64 nanoseconds\")?;\n        let updated = ts_event\n            .as_u64()\n            .checked_add(interval_ns)\n            .context(\"bar timestamp overflowed when adjusting to close time\")?;\n        ts_event = UnixNanos::from(updated);\n    }\n\n    let open = Price::from_decimal_dp(candle.open, price_precision)\n        .context(\"failed to parse candle open price\")?;\n    let high = Price::from_decimal_dp(candle.high, price_precision)\n        .context(\"failed to parse candle high price\")?;","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/http/parse.rs#L97-L133","documentation":"dYdX candle timestamps are returned as a Time type whose nanosecond value must fit into a u64 to build a UnixNanos bar timestamp. The adapter converts candle.started_at to nanoseconds and throws this error when the value is negative or exceeds u64 range. This guards against invalid or corrupted exchange timestamps producing nonsensical Bar timestamps.","triggerScenarios":"Calling request_bars (via parse_bar) when dYdX returns a candle whose started_at nanosecond value is negative or larger than u64::MAX — e.g. a far-future started_at from the exchange or a malformed candle payload.","commonSituations":"Exchange returning anomalous candle timestamps during API incidents; system clock/exchange time skew; parsing historical candles with corrupted started_at fields; downstream code misconfiguring timestamp conversion.","solutions":["Inspect the candle.started_at value logged in the message to confirm whether the exchange returned an out-of-range timestamp","Retry the bars request — a transient exchange glitch may have produced one bad candle","Verify the adapter/exchange SDK version so Time::as_nanosecond semantics match expected epoch nanos","Report or work around by filtering candles with implausible started_at values before parsing"],"exampleFix":"// before\nlet started_at_nanos = u64::try_from(candle.started_at.as_nanosecond())?;\n// after\nlet started_at_nanos = u64::try_from(candle.started_at.as_nanosecond())\n    .map_err(|_| anyhow::anyhow!(\"Timestamp out of range for candle at {}\", candle.started_at))?; // or skip/filter bad candles before parse_bar","handlingStrategy":"validation","validationCode":"let nanos = candle.started_at.as_nanosecond();\nif nanos < 0 || nanos > u64::MAX as i128 { skip_or_log(candle); return; }\n// safe: value now fits u64 before parse_bar\nlet ts = UnixNanos::from(nanos as u64);","typeGuard":"fn ts_in_range(t: dydx::Time) -> bool {\n    (0..=u64::MAX as i128).contains(&t.as_nanosecond())\n}","tryCatchPattern":"match parse_bar(...) {\n    Ok(bar) => process(bar),\n    Err(e) if e.to_string().contains(\"Timestamp out of range\") => skip_candle(),\n    Err(e) => return Err(e),\n}","preventionTips":["Filter candles with implausible started_at values before parsing","Pin adapter/exchange SDK versions and update deliberately","Monitor exchange API incidents that produce bad timestamps"],"tags":["rust","timestamp","parsing","dydx"],"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-14T00:17:10.932Z"}