nautechsystems/nautilus_trader · error

LiveNodeConfig.controller for importable controller '{}' req

Error message

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

What it means

Importable controllers are loaded via Python (Trader::add_controller_from_importable_config), which requires the crate's `python` feature. Building a live node whose config specifies a controller without that feature compiled in cannot load the controller and fails at build time.

Source

Thrown at crates/live/src/node/builder.rs:599

        let runner = AsyncRunner::new();
        runner.bind_senders();

        let socket_registry = SocketReconnectRegistry::default();

        let kernel = NautilusKernel::new_with_dependencies(
            self.name.clone(),
            self.config.clone(),
            NautilusKernelDependencies::default()
                .with_clock_factory(self.clock_factory.take())
                .with_event_store_factory(self.event_store_factory.take()),
        )?;
        #[cfg(feature = "python")]
        if let Some(controller) = self.config.controller.as_ref() {
            Trader::add_controller_from_importable_config(&kernel.trader, controller)?;
        }
        #[cfg(not(feature = "python"))]
        if let Some(controller) = self.config.controller.as_ref() {
            anyhow::bail!(
                "LiveNodeConfig.controller for importable controller '{}' requires the python feature",
                controller.controller_path
            );
        }

        self.install_external_msgbus_factory(&kernel)?;

        if let Some(external_egress) = self.external_msgbus_egress.take() {
            let config = self.config.msgbus.clone().unwrap_or_default();
            nautilus_common::msgbus::get_message_bus()
                .borrow_mut()
                .set_external_egress_config(external_egress, &config)?;
        }

        for (name, factory) in self.data_client_factories {
            if let Some(config) = self.data_client_configs.remove(&name) {
                log::debug!("Creating data client {name}");

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Rebuild with the `python` feature enabled (e.g. cargo build --features python).
  2. Remove the controller entry from LiveNodeConfig if Python support is not needed.
  3. Implement the controller natively in Rust instead of using an importable (Python) controller path.

Example fix

// before (Cargo.toml)
nautilus_live = { version = "..." }
// after
nautilus_live = { version = "...", features = ["python"] }
Defensive patterns

Strategy: validation

Validate before calling

if config.controller.is_some() && !cfg!(feature = "python") { /* controller unsupported in this build */ }

Try / catch

match node_build_result { Err(e) if e.to_string().contains("requires the python feature") => eprintln!("rebuild with --features python"), other => other? }

Prevention

When it happens

Trigger: LiveNodeConfig.controller = Some(...) (with a controller_path) while running a build of nautilus_live compiled without `--features python`, in LiveNodeBuilder::build.

Common situations: Deploying a Rust-only (no-Python) binary with a config copied from a Python setup; Cargo.toml missing the `python` feature; Docker image built without Python support but reusing an existing config file.

Related errors


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