nautechsystems/nautilus_trader · error · anyhow::Error

Unsupported aggregation: {:?}

Error message

Unsupported aggregation: {:?}

What it means

When paginating candle requests, `request_bars` converts bar durations to seconds, but only Minute, Hour, and Day aggregations are mapped. Any other aggregation (e.g. Second, Week, Month, Tick) fails with this error.

Source

Thrown at crates/adapters/dydx/src/http/client.rs:1109

        let instrument = self
            .get_instrument(&instrument_id)
            .ok_or_else(|| InstrumentLookupError::not_found(instrument_id))?;

        let ticker = extract_raw_symbol(instrument_id.symbol.as_str());
        let price_precision = instrument.price_precision();
        let size_precision = instrument.size_precision();
        let ts_init = self.generate_ts_init();

        let mut all_bars: Vec<Bar> = Vec::new();

        // Determine bar duration in seconds for pagination chunking
        let spec = bar_type.spec();
        let bar_secs: i64 = match spec.aggregation {
            BarAggregation::Minute => spec.step.get() as i64 * 60,
            BarAggregation::Hour => spec.step.get() as i64 * 3_600,
            BarAggregation::Day => spec.step.get() as i64 * 86_400,
            _ => anyhow::bail!("Unsupported aggregation: {:?}", spec.aggregation),
        };

        match (start, end) {
            // Time-chunked pagination for date ranges
            (Some(range_start), Some(range_end)) if range_end > range_start => {
                let overall_limit = limit.unwrap_or(u32::MAX);
                let mut remaining = overall_limit;
                let bars_per_call = DYDX_MAX_BARS_PER_REQUEST.min(remaining);
                let chunk_duration =
                    jiff::SignedDuration::from_secs(bar_secs * bars_per_call as i64);
                let mut chunk_start = range_start;

                while chunk_start < range_end && remaining > 0 {
                    let chunk_end = (chunk_start + chunk_duration).min(range_end);
                    let per_call_limit = remaining.min(DYDX_MAX_BARS_PER_REQUEST);

                    let response = self
                        .inner

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use Minute, Hour, or Day aggregation for dYdX bar requests
  2. Source sub-minute bars from another data provider or aggregate externally from trades
  3. Add Second support only if the upstream dYdX Indexer starts offering sub-minute candles

Example fix

// before
let spec = BarSpecification::new(15, BarAggregation::Second, PriceType::Last);
// after
let spec = BarSpecification::new(1, BarAggregation::Minute, PriceType::Last);
Defensive patterns

Strategy: validation

Validate before calling

matches!(bar_type.spec().aggregation, BarAggregation::Minute | BarAggregation::Hour | BarAggregation::Day);

Prevention

When it happens

Trigger: Calling `request_bars` with a `BarAggregation::Second` (e.g. 15-SECOND bars), `Tick`, `Week`, or `Month` bar type.

Common situations: Sub-minute bar requests against dYdX, which the Indexer candle endpoint does not offer; sharing bar-spec config across adapters where another venue supports seconds/ticks.

Related errors


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