nautechsystems/nautilus_trader · error

Cannot request aggregated bars: {bar_type} must be internall

Error message

Cannot request aggregated bars: {bar_type} must be internally aggregated

What it means

Requesting historical/aggregated bars through the request path requires every requested BarType to be internally aggregated, because the engine aggregates them with its own aggregators during the request. A bar type sourced from an external provider cannot be aggregated by the request pipeline, so the request is rejected.

Source

Thrown at crates/data/src/engine/requests.rs:296

        .context("`bar_types` request parameter must be an array")?;
    let mut bar_types = Vec::with_capacity(values.len());
    for value in values {
        let raw = value
            .as_str()
            .context("`bar_types` request parameter must contain strings")?;
        bar_types
            .push(BarType::from_str(raw).context("failed to parse `bar_types` request parameter")?);
    }

    if bar_types.is_empty() {
        return Ok(None);
    }

    if let Some(bar_type) = bar_types
        .iter()
        .find(|bar_type| !bar_type.is_internally_aggregated())
    {
        anyhow::bail!("Cannot request aggregated bars: {bar_type} must be internally aggregated");
    }

    let mut unique_bar_types = Vec::with_capacity(bar_types.len());
    for bar_type in bar_types {
        if !unique_bar_types.contains(&bar_type) {
            unique_bar_types.push(bar_type);
        }
    }

    let update_subscriptions = params.get_bool("update_subscriptions").unwrap_or(false);
    let skip_first_non_full_bar = params.get_bool("skip_first_non_full_bar");

    Ok(Some(RequestBarAggregation {
        bar_types: unique_bar_types,
        update_subscriptions,
        disable_build_with_no_updates: false,
        skip_first_non_full_bar,
    }))

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Drop the external aggregation source from the requested bar types so they default to internal aggregation.
  2. If the data is only available externally, use a direct historical request to the data client instead of the internal aggregation request path.
  3. Validate all bar types with bar_type.is_internally_aggregated() before issuing the request.

Example fix

// before
client.request_bars(BarType::from_str("AAPL.XNAS-5-MINUTE-LAST:external")?)?;
// after
client.request_bars(BarType::from_str("AAPL.XNAS-5-MINUTE-LAST")?)?;
Defensive patterns

Strategy: validation

Validate before calling

if bar_types.iter().any(|bt| !bt.is_internally_aggregated()) {
    anyhow::bail!("all requested bar types must be internally aggregated");
}

Type guard

fn all_internally_aggregated(bts: &[BarType]) -> bool {
    bts.iter().all(|bt| bt.is_internally_aggregated())
}

Try / catch

match client.request_bars(bar_types, ...) {
    Err(e) if e.to_string().contains("must be internally aggregated") => {
        let fixed: Vec<BarType> = bar_types.into_iter().map(|bt| bt.to_internal_aggregation()).collect();
        client.request_bars(fixed, ...)?;
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling prepare_request_bar_aggregators / request_bar_aggregation_from_params (e.g. RequestBars via strategy.request_bars) where at least one BarType in the bar_types param has AggregationSource::External.

Common situations: Building bar type strings with ':external' suffix in a historical data request; reusing live-subscription bar types (externally fed by an adapter) in a backtest/history request; config templates that specify external aggregation.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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