nautechsystems/nautilus_trader · error

Cannot start bar aggregation for {bar_type}

Error message

Cannot start bar aggregation for {bar_type}

What it means

After creating a bar aggregator for the given bar type and request ID, the engine looks it up in the bar_aggregators map and fails if it is absent. This is an internal invariant check immediately following create_bar_aggregator_for_key, so hitting it means aggregator creation silently failed or the entry was evicted concurrently.

Source

Thrown at crates/data/src/engine/mod.rs:4917

        );

        Ok(())
    }

    fn start_bar_aggregator(
        &mut self,
        bar_type: BarType,
        request_id: Option<UUID4>,
        skip_first_non_full_bar: Option<bool>,
    ) -> anyhow::Result<()> {
        let key = bar_aggregator_key(bar_type, request_id);
        let bar_type_std = bar_type.standard();

        self.create_bar_aggregator_for_key(bar_type, request_id, skip_first_non_full_bar)?;
        let aggregator = self
            .bar_aggregators
            .get(&key)
            .ok_or_else(|| anyhow::anyhow!("Cannot start bar aggregation for {bar_type}"))?
            .clone();
        let defer_subscription_activation = request_id.is_none()
            && aggregator.borrow().is_running()
            && !self.bar_aggregator_handlers.contains_key(&key);

        if !self.bar_aggregator_handlers.contains_key(&key) {
            // Subscribe to underlying data topics
            let mut subscriptions = Vec::new();

            if bar_type.is_composite() {
                let topic = switchboard::get_bars_topic(bar_type.composite());
                let handler = TypedHandler::new(BarBarHandler::new(&aggregator, bar_type_std));
                msgbus::subscribe_bars(topic.into(), handler.clone(), None);
                subscriptions.push(BarAggregatorSubscription::Bar { topic, handler });
            } else if bar_type.spec().price_type == PriceType::Last {
                let topic = switchboard::get_trades_topic(bar_type.instrument_id());
                let handler = TypedHandler::new(BarTradeHandler::new(&aggregator, bar_type_std));
                msgbus::subscribe_trades(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Retry the subscription once — if transient concurrency caused the miss, a fresh call recreates the aggregator.
  2. Check for concurrent subscribe/stop calls on the same BarType (e.g. an unsubscribe racing the subscribe) and serialize them.
  3. Verify the aggregator key derivation (bar_aggregator_key) is consistent between creation and lookup; update to a version where creation and lookup share one key.
  4. File an issue with the bar_type and call stack — this indicates an engine bug rather than user error.
Defensive patterns

Strategy: retry

Validate before calling

if engine.is_subscribed_bars(&bar_type) {
    // already active, skip create/start path
}

Try / catch

match result {
    Err(e) if e.to_string().contains("Cannot start bar aggregation") => {
        // retry once after a short delay; else surface as engine bug
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling start_bar_aggregation / subscribe_bars where create_bar_aggregator_for_key succeeded but self.bar_aggregators.get(&key) returns None — effectively an internal invariant violation in the aggregator registry.

Common situations: Race conditions between concurrent subscribe/stop calls on the same bar type; forked engine state where the creation path was patched; custom request_id handling causing key mismatch.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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