{"record":{"id":"c8c81a9a1fa2a6ef","repo":"nautechsystems/nautilus_trader","slug":"python-on-order-failed-e","errorCode":null,"errorMessage":"Python on_order failed: {e}","messagePattern":"Python on_order failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/python/actor.rs","lineNumber":264,"sourceCode":"}\n\n#[expect(clippy::needless_pass_by_ref_mut)]\nimpl PyDataActorInner {\n    fn execute_exec_algorithm_command(&mut self, command: &TradingCommand) -> anyhow::Result<()> {\n        if self.core.config.log_commands {\n            let id = self.core.actor_id;\n            log::info!(\"{id} {RECV}{CMD} {command}\");\n        }\n\n        if self.core.state() != ComponentState::Running {\n            return Ok(());\n        }\n\n        match command {\n            TradingCommand::SubmitOrder(cmd) => {\n                let order = DataActor::cache(self).try_order(&cmd.client_order_id)?;\n                self.dispatch_on_order(order)\n                    .map_err(|e| anyhow::anyhow!(\"Python on_order failed: {e}\"))\n            }\n            TradingCommand::SubmitOrderList(cmd) => {\n                let orders = self.orders_for_list(&cmd.order_list)?;\n                self.dispatch_on_order_list(cmd.order_list.clone(), orders)\n                    .map_err(|e| anyhow::anyhow!(\"Python on_order_list failed: {e}\"))\n            }\n            _ => {\n                log::warn!(\"Unhandled command type: {command}\");\n                Ok(())\n            }\n        }\n    }\n\n    fn orders_for_list(&self, order_list: &OrderList) -> anyhow::Result<Vec<OrderAny>> {\n        let cache = DataActor::cache(self);\n        let mut orders = Vec::with_capacity(order_list.client_order_ids.len());\n\n        for client_order_id in &order_list.client_order_ids {","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/python/actor.rs#L246-L282","documentation":"DataActor command execution wraps the Python on_order callback; any exception raised inside the user's Python on_order handler is converted into this anyhow error by execute_exec_algorithm_command. It means the exec algorithm's Python-level order-submission handler failed, aborting the SubmitOrder trading command.","triggerScenarios":"An exec algorithm command TradingCommand::SubmitOrder is executed and the actor's dispatch_on_order invokes the Python on_order override, which raises an exception (bad attribute, missing cache data, invalid order state, Python bug).","commonSituations":"User-defined on_order in a Python exec algorithm references an attribute not yet initialized, handles orders whose instrument is missing from cache, or throws on None/odd order states during live reconciliation.","solutions":["Read the chained '{e}' cause to find the underlying Python exception and fix the on_order handler","Guard on_order with checks that the order and its instrument exist in cache before use","Test the exec algorithm with a backtest covering submit-order paths before live use","Log and handle expected edge cases (e.g. denied/canceled orders) inside on_order instead of raising"],"exampleFix":"# before\ndef on_order(self, order):\n    instrument = self.cache.instrument(order.instrument_id)\n    price = instrument.make_price(self.limit)  # raises if instrument is None\n# after\ndef on_order(self, order):\n    instrument = self.cache.instrument(order.instrument_id)\n    if instrument is None:\n        self.log.error(f\"No instrument for {order.instrument_id}\")\n        return\n    price = instrument.make_price(self.limit)","handlingStrategy":"try-catch","validationCode":"def check_order_ready(order) -> bool:\n    return (\n        order is not None\n        and self.cache.instrument(order.instrument_id) is not None\n        and order.client_order_id is not None\n    )","typeGuard":"def order_in_cache(self, order) -> bool:\n    return self.cache.order(order.client_order_id) is not None","tryCatchPattern":"def on_order(self, order):\n    try:\n        self._handle_order(order)\n    except Exception as e:\n        self.log.exception(f\"on_order failed for {order.client_order_id}: {e}\")\n        # do not re-raise unless the actor must halt","preventionTips":["Always handle None instruments/missing cache entries in on_order","Log inside handlers so failures carry context beyond the generic wrapper message","Backtest the exec algorithm's order paths before live use","Keep on_order lightweight; defer heavy work to timers"],"tags":["python","actor","exec-algorithm","callback"],"backgroundTag":"internal-invariant-violation","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"}