nautechsystems/nautilus_trader · error

Only one run config per BacktestNode is supported (kernel Me

Error message

Only one run config per BacktestNode is supported (kernel MessageBus is a thread-local singleton)

What it means

BacktestNode only supports a single run config because the kernel MessageBus is a thread-local singleton that can only be initialized once per thread; multiple engines cannot coexist. validate_configs rejects any config list longer than one.

Source

Thrown at crates/backtest/src/node.rs:313

            let ids: Vec<String> = instr_ids.iter().map(ToString::to_string).collect();
            anyhow::bail!(
                "No instruments found in catalog for requested IDs: [{}]",
                ids.join(", ")
            );
        }

        for instrument in instruments {
            engine.add_instrument(&instrument)?;
        }
    }

    Ok(engine)
}

fn validate_configs(configs: &[BacktestRunConfig]) -> anyhow::Result<()> {
    // Kernel initialization sets a thread-local MessageBus that can only be
    // initialized once per thread, so multiple engines cannot coexist
    anyhow::ensure!(
        configs.len() <= 1,
        "Only one run config per BacktestNode is supported \
         (kernel MessageBus is a thread-local singleton)"
    );

    let mut seen_ids = AHashSet::new();

    for config in configs {
        anyhow::ensure!(
            seen_ids.insert(config.id()),
            "Duplicate run config ID '{}'",
            config.id()
        );

        let venue_names: Vec<String> = config
            .venues()
            .iter()
            .map(|v| v.name().to_string())

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Create one BacktestNode per run config and run them sequentially
  2. Run each config in its own thread/process if parallelism is needed
  3. Aggregate results yourself after running nodes one at a time
  4. Check the current API/docs whether multi-run support has since been added

Example fix

// before
let node = BacktestNode::new(vec![cfg_a, cfg_b])?;
// after
for cfg in [cfg_a, cfg_b] {
    let node = BacktestNode::new(vec![cfg])?;
    node.run()?;
}
Defensive patterns

Strategy: validation

Validate before calling

if configs.len() > 1 { panic!("BacktestNode supports only one run config"); }

Try / catch

match BacktestNode::new(configs) {
    Ok(node) => node,
    Err(e) if e.to_string().contains("Only one run config") => {
        for cfg in configs { BacktestNode::new(vec![cfg])?.run()?; }
        unreachable!()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing two or more BacktestRunConfig values to `BacktestNode::new`, expecting multi-run (parameter sweep / portfolio of backtests) behavior.

Common situations: Migrating code that assumed multi-run support; building a batch of scenario configs in a loop and collecting them all into one node; parallel backtest sweeps.

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/bd6d2ef069219bfd. Report an issue: GitHub.