{"record":{"id":"04f048d4fc9ca594","repo":"nautechsystems/nautilus_trader","slug":"python-override-lookup-failed-e","errorCode":null,"errorMessage":"Python override lookup failed: {e}","messagePattern":"Python override lookup failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/trading/src/python/algorithm.rs","lineNumber":403,"sourceCode":"    fn exec_algorithm_core_mut(&mut self) -> &mut ExecutionAlgorithmCore {\n        &mut self.inner_mut().core\n    }\n}\n\nimpl ExecutionAlgorithm for PyExecutionAlgorithm {\n    fn on_order(&mut self, order: OrderAny) -> anyhow::Result<()> {\n        self.dispatch_on_order(order)\n            .map_err(|e| anyhow::anyhow!(\"Python on_order failed: {e}\"))\n    }\n\n    fn on_order_list(\n        &mut self,\n        order_list: OrderList,\n        orders: Vec<OrderAny>,\n    ) -> anyhow::Result<()> {\n        if self\n            .has_python_override(\"on_order_list\")\n            .map_err(|e| anyhow::anyhow!(\"Python override lookup failed: {e}\"))?\n        {\n            return self\n                .dispatch_on_order_list(order_list, orders)\n                .map_err(|e| anyhow::anyhow!(\"Python on_order_list failed: {e}\"));\n        }\n\n        for order in orders {\n            self.on_order(order)?;\n        }\n        Ok(())\n    }\n\n    fn on_start(&mut self) -> anyhow::Result<()> {\n        log::info!(\"Starting {}\", self.exec_algorithm_id());\n        Ok(())\n    }\n\n    fn on_stop(&mut self) -> anyhow::Result<()> {","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/trading/src/python/algorithm.rs#L385-L421","documentation":"Before dispatching `on_order_list`, PyExecutionAlgorithm checks whether the Python object overrides the method using `has_python_override`. If that reflective lookup itself fails (an exception crossing the PyO3 boundary, e.g. calling into Python raised), it is re-wrapped with this message. This is distinct from the callback failing: the lookup of whether the callback exists failed.","triggerScenarios":"Calling on_order_list when `has_python_override(\"on_order_list\")` returns Err — e.g. the wrapped Python object is in a bad state, its class introspection fails, or the Python runtime raised during attribute access.","commonSituations":"A broken proxy/wrapper class that raises in __getattr__; PyO3 conversion errors when inspecting the instance; interpreter shutdown/initialization issues during attribute lookup.","solutions":["Inspect the chained `{e}` for the underlying Python exception raised during attribute lookup and fix the wrapper class.","Ensure the Python algorithm class is a plain class exposing on_order_list/on_order without a __getattr__ that can raise.","Verify the PyExecutionAlgorithm holds a live Python object (not a dropped/GC'd reference) before dispatch.","Update/align the pyo3 binding version if introspection APIs changed."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# Python: ensure the class is introspectable (no raising __getattr__)\nassert hasattr(type(algo), \"on_order_list\") or hasattr(algo, \"on_order_list\")","typeGuard":null,"tryCatchPattern":"match algo.on_order_list(order_list, orders) {\n    Ok(()) => {},\n    Err(e) => log::error!(\"on_order_list dispatch failed: {e:#}\"),\n}","preventionTips":["Avoid __getattr__ implementations that can raise on the algorithm class.","Hold the Python object with a stable Py<PyAny> reference for the algorithm's lifetime.","Pin and test against the pyo3 version used by the bindings."],"tags":["rust","python","pyo3","override-lookup","introspection"],"backgroundTag":"api-error-response","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}