{"record":{"id":"a4936ac6ef965f1b","repo":"nautechsystems/nautilus_trader","slug":"controller-must-inherit-from-nautilus-trader-trad","errorCode":null,"errorMessage":"Controller must inherit from `nautilus_trader.trading.Controller`: {e}","messagePattern":"Controller must inherit from `nautilus_trader\\.trading\\.Controller`: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/system/src/python/controller.rs","lineNumber":209,"sourceCode":"    }\n\n    #[pyo3(name = \"remove_strategy_from_id\")]\n    fn py_remove_strategy_from_id(slf: PyRef<'_, Self>, strategy_id: StrategyId) -> PyResult<()> {\n        Self::py_remove_strategy(slf, strategy_id)\n    }\n}\n\n/// Binds the registered trader to a user-authored Python controller instance.\npub(crate) fn bind_controller_trader(\n    python_controller: &Py<PyAny>,\n    trader: &Rc<RefCell<Trader>>,\n) -> anyhow::Result<()> {\n    Python::attach(|py| -> anyhow::Result<()> {\n        let mut controller = python_controller\n            .bind(py)\n            .extract::<PyRefMut<PyController>>()\n            .map_err(|e| {\n                anyhow::anyhow!(\n                    \"Controller must inherit from `nautilus_trader.trading.Controller`: {e}\"\n                )\n            })?;\n\n        controller.bind_trader(trader);\n\n        Ok(())\n    })\n}\n","sourceCodeStart":191,"sourceCodeEnd":219,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/system/src/python/controller.rs#L191-L219","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nclass MyController:\n    def stop(self): ...\n\n// after\nfrom nautilus_trader.trading import Controller\n\nclass MyController(Controller):\n    def stop(self): ...","handlingStrategy":"type-guard","validationCode":"from nautilus_trader.trading import Controller\nassert isinstance(my_controller, Controller), \"controller must subclass Controller\"","typeGuard":"def is_controller(obj) -> bool:\n    from nautilus_trader.trading import Controller\n    return isinstance(obj, Controller)","tryCatchPattern":"try:\n    bind_controller_trader(controller, trader)\nexcept Exception as e:\n    if \"must inherit\" in str(e):\n        raise TypeError(f\"{type(controller).__name__} must subclass nautilus_trader.trading.Controller\") from e\n    raise","preventionTips":["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."],"tags":["python","pyo3","type-mismatch","controller"],"backgroundTag":"type-mismatch","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}