nautechsystems/nautilus_trader · error · anyhow::Error

Timestamp out of range for candle at {}

Error message

Timestamp out of range for candle at {}

What it means

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.

Source

Thrown at crates/adapters/dydx/src/http/parse.rs:115

/// Parses a dYdX [`Candle`] into a Nautilus [`Bar`].
///
/// When `timestamp_on_close` is true, `ts_event` is set to bar close time
/// (started_at + interval). When false, uses the venue-native open time.
///
/// # Errors
///
/// Returns an error if OHLCV or timestamp conversion fails.
pub fn parse_bar(
    candle: &Candle,
    bar_type: BarType,
    price_precision: u8,
    size_precision: u8,
    timestamp_on_close: bool,
    ts_init: UnixNanos,
) -> anyhow::Result<Bar> {
    let started_at_nanos = u64::try_from(candle.started_at.as_nanosecond()).map_err(|_| {
        anyhow::anyhow!("Timestamp out of range for candle at {}", candle.started_at)
    })?;
    let mut ts_event = UnixNanos::from(started_at_nanos);

    if timestamp_on_close {
        let interval_ns = bar_type.spec().timedelta().as_nanos();
        let interval_ns =
            u64::try_from(interval_ns).context("bar interval overflowed u64 nanoseconds")?;
        let updated = ts_event
            .as_u64()
            .checked_add(interval_ns)
            .context("bar timestamp overflowed when adjusting to close time")?;
        ts_event = UnixNanos::from(updated);
    }

    let open = Price::from_decimal_dp(candle.open, price_precision)
        .context("failed to parse candle open price")?;
    let high = Price::from_decimal_dp(candle.high, price_precision)
        .context("failed to parse candle high price")?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the candle.started_at value logged in the message to confirm whether the exchange returned an out-of-range timestamp
  2. Retry the bars request — a transient exchange glitch may have produced one bad candle
  3. Verify the adapter/exchange SDK version so Time::as_nanosecond semantics match expected epoch nanos
  4. Report or work around by filtering candles with implausible started_at values before parsing

Example fix

// before
let started_at_nanos = u64::try_from(candle.started_at.as_nanosecond())?;
// after
let started_at_nanos = u64::try_from(candle.started_at.as_nanosecond())
    .map_err(|_| anyhow::anyhow!("Timestamp out of range for candle at {}", candle.started_at))?; // or skip/filter bad candles before parse_bar
Defensive patterns

Strategy: validation

Validate before calling

let nanos = candle.started_at.as_nanosecond();
if nanos < 0 || nanos > u64::MAX as i128 { skip_or_log(candle); return; }
// safe: value now fits u64 before parse_bar
let ts = UnixNanos::from(nanos as u64);

Type guard

fn ts_in_range(t: dydx::Time) -> bool {
    (0..=u64::MAX as i128).contains(&t.as_nanosecond())
}

Try / catch

match parse_bar(...) {
    Ok(bar) => process(bar),
    Err(e) if e.to_string().contains("Timestamp out of range") => skip_candle(),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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