nautechsystems/nautilus_trader · error
Controller must inherit from `nautilus_trader.trading.Contro
Error message
Controller must inherit from `nautilus_trader.trading.Controller`: {e} What it means
`bind_controller_trader` extracts the passed Python controller object into `PyRefMut<PyController>`. PyO3's `extract` only succeeds if the Python object's class actually inherits from `nautilus_trader.trading.Controller` (the Rust-exposed base). Any other object raises this error.
Source
Thrown at crates/system/src/python/controller.rs:209
}
#[pyo3(name = "remove_strategy_from_id")]
fn py_remove_strategy_from_id(slf: PyRef<'_, Self>, strategy_id: StrategyId) -> PyResult<()> {
Self::py_remove_strategy(slf, strategy_id)
}
}
/// Binds the registered trader to a user-authored Python controller instance.
pub(crate) fn bind_controller_trader(
python_controller: &Py<PyAny>,
trader: &Rc<RefCell<Trader>>,
) -> anyhow::Result<()> {
Python::attach(|py| -> anyhow::Result<()> {
let mut controller = python_controller
.bind(py)
.extract::<PyRefMut<PyController>>()
.map_err(|e| {
anyhow::anyhow!(
"Controller must inherit from `nautilus_trader.trading.Controller`: {e}"
)
})?;
controller.bind_trader(trader);
Ok(())
})
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Make the controller class inherit from `nautilus_trader.trading.Controller`.
- Ensure you pass the controller instance (not its config or class) to the binding API.
- Check that the installed nautilus_trader package exposes the same Controller base the Rust binding expects (matching versions).
Example fix
// before
class MyController:
def stop(self): ...
// after
from nautilus_trader.trading import Controller
class MyController(Controller):
def stop(self): ... Defensive patterns
Strategy: type-guard
Validate before calling
from nautilus_trader.trading import Controller assert isinstance(my_controller, Controller), "controller must subclass Controller"
Type guard
def is_controller(obj) -> bool:
from nautilus_trader.trading import Controller
return isinstance(obj, Controller) Try / catch
try:
bind_controller_trader(controller, trader)
except Exception as e:
if "must inherit" in str(e):
raise TypeError(f"{type(controller).__name__} must subclass nautilus_trader.trading.Controller") from e
raise Prevention
- Always subclass nautilus_trader.trading.Controller for custom controllers.
- Unit-test controller wiring with isinstance assertions before live wiring.
- Pass instances, never classes or configs, to binding APIs.
When it happens
Trigger: Passing a Python object to the controller binding API whose class does not subclass `nautilus_trader.trading.Controller` — e.g. a custom controller implementing the methods duck-typed but without inheriting the base class, or a None/mistyped argument.
Common situations: Writing a custom live controller and forgetting `from nautilus_trader.trading import Controller` inheritance; passing a config object instead of the controller instance; typos importing a different Controller class.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Failed to extract PyStrategy: {e}
- Failed to extract PyDataActor: {e}
- Invalid `actor_id` type
- LiveNodeConfig.controller for importable controller '{}' req
- Invalid `exec_algorithm_id`/`actor_id` type
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a4936ac6ef965f1b.
Report an issue: GitHub.