nautechsystems/nautilus_trader · error

BacktestEngineConfig.controller for importable controller '{

Error message

BacktestEngineConfig.controller for importable controller '{}' requires the python feature

What it means

BacktestEngineConfig supports an importable Python controller, but wiring one requires the crate's `python` feature. When the engine is built without Python bindings and a controller is configured, construction fails with this error instead of silently ignoring the controller.

Source

Thrown at crates/backtest/src/engine.rs:155

    ///
    /// # Errors
    ///
    /// Returns an error if the core `NautilusKernel` fails to initialize.
    pub fn new(mut config: BacktestEngineConfig) -> anyhow::Result<Self> {
        // The engine does not replay `add_instrument` on reset, so reruns rely
        // on the cache retaining instruments regardless of the caller's config.
        let mut cache_config = config.cache.unwrap_or_default();
        cache_config.drop_instruments_on_reset = false;
        config.cache = Some(cache_config);
        let kernel = NautilusKernel::new("BacktestEngine".to_string(), config.clone())?;
        let instance_id = kernel.instance_id;
        #[cfg(feature = "python")]
        if let Some(controller) = config.controller.as_ref() {
            Trader::add_controller_from_importable_config(&kernel.trader, controller)?;
        }
        #[cfg(not(feature = "python"))]
        if let Some(controller) = config.controller.as_ref() {
            anyhow::bail!(
                "BacktestEngineConfig.controller for importable controller '{}' requires the python feature",
                controller.controller_path
            );
        }

        Ok(Self {
            kernel,
            instance_id,
            config,
            accumulator: TimeEventAccumulator::new(),
            run_config_id: None,
            run_id: None,
            venues: IndexMap::new(),
            exec_clients: Vec::new(),
            has_data: AHashSet::new(),
            has_book_data: AHashSet::new(),
            has_book_processed: AHashSet::new(),
            data_iterator: BacktestDataIterator::new(),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Rebuild with the python feature enabled (e.g. `cargo build --features python`)
  2. Remove `controller` from the BacktestEngineConfig for Rust-only builds
  3. Conditionally set the controller in config loading based on build features
  4. Use a Rust-native controller implementation if available instead of the importable Python one

Example fix

// before
let engine = BacktestEngine::new(Some(config_with_controller), None)?;  // no python feature
// after
cargo build --features python
// or remove the controller:
config.controller = None;
Defensive patterns

Strategy: validation

Validate before calling

#[cfg(not(feature = "python"))]
if config.controller.is_some() {
    panic!("controller configured but built without the python feature");
}

Try / catch

let engine = BacktestEngine::new(Some(config), None)
    .map_err(|e| if e.to_string().contains("requires the python feature") {
        anyhow::anyhow!("Rebuild with --features python or drop config.controller")
    } else { e })?;

Prevention

When it happens

Trigger: Constructing a BacktestEngine with config.controller set to Some(ImportableControllerConfig{..}) while the nautilus crate was compiled without the `python` feature (e.g. a pure-Rust build).

Common situations: Using a config file generated from a Python environment in a Rust-only binary; enabling the controller field by default in shared config tooling; a build without `--features python`.

Related errors


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