nautechsystems/nautilus_trader · error

Only EXTERNAL aggregation is supported

Error message

Only EXTERNAL aggregation is supported

What it means

The spot HTTP client only supports requesting bars whose aggregation comes from the venue (AggregationSource::External). Bars with Internal aggregation are generated by Nautilus from lower-level data and cannot be fetched from Binance, so the request is rejected up front.

Source

Thrown at crates/adapters/binance/src/spot/http/client.rs:2969

            trade.ts_init = trade.ts_event;
        }
        Ok(parsed)
    }

    /// Requests bar (kline/candlestick) data.
    ///
    /// # Errors
    ///
    /// Returns an error if the bar type is not supported, instrument is not cached,
    /// or the request fails.
    pub async fn request_binance_bars(
        &self,
        bar_type: BarType,
        start: Option<Timestamp>,
        end: Option<Timestamp>,
        limit: Option<u32>,
    ) -> anyhow::Result<Vec<crate::common::bar::BinanceBar>> {
        anyhow::ensure!(
            bar_type.aggregation_source() == AggregationSource::External,
            "Only EXTERNAL aggregation is supported"
        );

        let spec = bar_type.spec();
        let step = spec.step.get();
        let interval = match spec.aggregation {
            BarAggregation::Second if step == 1 => "1s".to_string(),
            BarAggregation::Second => {
                anyhow::bail!("Binance Spot supports only the 1s kline interval")
            }
            BarAggregation::Minute => format!("{step}m"),
            BarAggregation::Hour => format!("{step}h"),
            BarAggregation::Day => format!("{step}d"),
            BarAggregation::Week => format!("{step}w"),
            BarAggregation::Month => format!("{step}M"),
            a => anyhow::bail!("Binance does not support {a:?} aggregation"),
        };

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use an External aggregation source in the BarType for historical bar requests
  2. For internally aggregated bars, request the underlying trades/quotes and aggregate locally
  3. Fix the BarType string suffix from -INTERNAL to -EXTERNAL
  4. Document in your actor which bar types are venue-provided

Example fix

// before
let bar_type = BarType::from_str("BTCUSDT-BINANCE-1-MINUTE-LAST-INTERNAL").unwrap();
// after
let bar_type = BarType::from_str("BTCUSDT-BINANCE-1-MINUTE-LAST-EXTERNAL").unwrap();
Defensive patterns

Strategy: validation

Validate before calling

if bar_type.aggregation_source() != AggregationSource::External {
    return Err("historical bar requests require AggregationSource::External");
}

Type guard

fn is_externally_aggregated(bt: &BarType) -> bool { bt.aggregation_source() == AggregationSource::External }

Try / catch

match result { Err(e) if e.to_string().contains("Only EXTERNAL aggregation") => switch_to_external_bar_type_and_retry(), Err(e) => return Err(e), Ok(bars) => Ok(bars) }

Prevention

When it happens

Trigger: Requesting historical bars via request_bars with a BarType built with AggregationSource.Internal — e.g. BarType::from_str("BTCUSDT-BINANCE-1-MINUTE-LAST-INTERNAL") — or a strategy configured with internal bar aggregation while asking the client to fetch history.

Common situations: Copy-pasting BarType strings from internal-aggregation examples into a historical request; confusion between subscribed (internally synthesized) bars and externally fetched venue bars.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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