nautechsystems/nautilus_trader · error

Continuous future bar subscription requires `continuous_futu

Error message

Continuous future bar subscription requires `continuous_future_transitions`, was {cmd:?}

What it means

Subscribing to continuous future bars requires the SubscribeBars command to carry continuous_future_transitions data. continuous_future_subscription_from_bars(cmd) returns None when the command's transitions payload is absent, meaning the command cannot describe how the continuous future rolls between contracts. The engine bails rather than silently aggregating bars without roll definitions.

Source

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

    fn subscribe_continuous_future_bars(&mut self, cmd: &SubscribeBars) -> anyhow::Result<()> {
        let target_bar_type = cmd.bar_type;
        let target_key = target_bar_type.standard();

        if !target_bar_type.is_internally_aggregated() {
            anyhow::bail!(
                "Continuous future bar subscriptions require an internally aggregated target, was {target_bar_type}"
            );
        }

        if self.continuous_future_roller.is_none() {
            anyhow::bail!(
                "Cannot subscribe continuous future bars for {target_bar_type}: roller is not initialized; ensure `register_msgbus_handlers` runs before subscribing"
            );
        }

        let request = continuous_future_subscription_from_bars(cmd)?.ok_or_else(|| {
            anyhow::anyhow!(
                "Continuous future bar subscription requires `continuous_future_transitions`, was {cmd:?}"
            )
        })?;

        self.ensure_continuous_future_target_instrument(&request);

        if self
            .continuous_future_subscriptions
            .contains_key(&target_key)
        {
            log::warn!("Continuous future bars already subscribed for {target_bar_type}");
            return Ok(());
        }

        let aggregator_key = bar_aggregator_key(target_bar_type, None);
        if let Some(aggregator) = self.bar_aggregators.get(&aggregator_key)
            && aggregator.borrow().is_running()
        {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure register_msgbus_handlers has run and the continuous future roller is initialized before subscribing.
  2. Use the standard subscribe_bars API on the DataEngine/TradingNode instead of hand-building the SubscribeBars command, so transitions are populated automatically.
  3. Load continuous future transitions into the cache (via the instrument provider / request) before subscribing to the continuous bar type.
  4. If only regular bars are intended, use a non-continuous BarType (standard instrument ID) — continuous subscription support is limited to commands carrying transitions.

Example fix

// before
let cmd = SubscribeBars::new(bar_type, client_id, None); // no transitions
// after
let transitions = cache.continuous_future_transitions(&bar_type.instrument_id());
let cmd = SubscribeBars::new(bar_type, client_id, None)
    .with_continuous_future_transitions(transitions);
Defensive patterns

Strategy: validation

Validate before calling

let is_continuous = matches!(&bar_type, BarType::Continuous(_));
if is_continuous {
    let transitions = cache.continuous_future_transitions(&bar_type.instrument_id());
    assert!(transitions.is_some(), "continuous future transitions must be loaded before subscribing");
}

Type guard

fn has_transitions(cmd: &SubscribeBars) -> bool {
    cmd.continuous_future_transitions.is_some()
}

Try / catch

if let Err(e) = engine.subscribe_bars(&bar_type) {
    if e.to_string().contains("continuous_future_transitions") {
        // load transitions / initialize roller, then retry
    }
}

Prevention

When it happens

Trigger: Sending a SubscribeBars command for a continuous future symbol (e.g. ES.CME with roll rules) where cmd.continuous_future_transitions is None — typically when the command was built without fetching transitions from the cache/extrema, or when the roller was not initialized (see the preceding roller check).

Common situations: Custom or scripted subscription paths constructing SubscribeBars manually without populating transitions; register_msgbus_handlers not run so the roller/transition machinery is uninitialized; subscribing to continuous futures before the instrument provider has loaded transitions.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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