{"record":{"id":"569b0456bb48dc97","repo":"nautechsystems/nautilus_trader","slug":"failed-to-send-order-updated-event-e","errorCode":null,"errorMessage":"Failed to send order updated event: {e}","messagePattern":"Failed to send order updated event: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/execution/core_updates.rs","lineNumber":429,"sourceCode":"            strategy_id,\n            instrument_id,\n            client_order_id,\n            quantity,\n            UUID4::new(),\n            ts_init,\n            ts_init,\n            false,\n            Some(venue_order_id),\n            Some(account_id),\n            price,\n            trigger_price,\n            None,\n            false,\n        );\n\n        exec_sender\n            .send(ExecutionEvent::Order(OrderEventAny::Updated(event)))\n            .map_err(|e| anyhow::anyhow!(\"Failed to send order updated event: {e}\"))\n    }\n\n    fn open_order_price_fields(\n        order_data: &ibapi::orders::OrderData,\n        price_magnifier: f64,\n        price_precision: u8,\n    ) -> (Option<Price>, Option<Price>) {\n        let order_type = IbOrderType::from_str(order_data.order.order_type.as_str())\n            .map_or(OrderType::Market, IbOrderType::nautilus_order_type);\n        let price = order_data\n            .order\n            .limit_price\n            .map(|price| Price::new(price * price_magnifier, price_precision));\n        let trigger_price = order_data\n            .order\n            .aux_price\n            .map(|price| Price::new(price * price_magnifier, price_precision));\n","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/execution/core_updates.rs#L411-L447","documentation":"The Interactive Brokers execution adapter failed to deliver an OrderUpdated event through the internal exec_sender mpsc channel. This means the receiving side of the channel has been dropped or closed while the adapter was processing an IB OpenOrder callback. It indicates the execution event pipeline is torn down but the adapter is still receiving venue updates.","triggerScenarios":"emit_order_updated_from_open_order calls exec_sender.send(ExecutionEvent::Order(OrderEventAny::Updated(event))) and the receiver half of the channel has been dropped (e.g. the ExecutionEngine or the task consuming execution events was shut down) so send returns Err.","commonSituations":"Engine shutdown while IB still streams open-order updates; a panicking or prematurely-stopped consumer task; reconnect storms where the adapter outlives the event receiver.","solutions":["Ensure the execution event consumer (ExecutionEngine) is kept alive as long as the IB adapter is connected and subscribed to open orders.","Shut down the IB adapter's order stream before dropping the event receiver, so no sends happen after teardown.","If shutdown is intentional, downgrade handling of this Err to a log rather than propagating it as a fatal error."],"exampleFix":"// before\nexec_sender\n    .send(ExecutionEvent::Order(OrderEventAny::Updated(event)))\n    .map_err(|e| anyhow::anyhow!(\"Failed to send order updated event: {e}\"))\n// after\nif let Err(e) = exec_sender.send(ExecutionEvent::Order(OrderEventAny::Updated(event))) {\n    tracing::warn!(\"Execution channel closed, dropping order updated event: {e}\");\n    return Ok(());\n}\nOk(())","handlingStrategy":"try-catch","validationCode":"// Rust: check channel liveness before producing events\nif exec_sender.is_closed() {\n    tracing::warn!(\"Execution event channel closed; not emitting order updated event\");\n    return Ok(());\n}","typeGuard":"fn can_send(sender: &mpsc::Sender<ExecutionEvent>) -> bool {\n    !sender.is_closed()\n}","tryCatchPattern":"match exec_sender.send(event) {\n    Ok(()) => {}\n    Err(e) => tracing::warn!(\"Order updated event dropped, channel closed: {e}\"),\n}","preventionTips":["Tie adapter lifetime to the execution engine lifetime so receivers are never dropped first","Use scoped shutdown ordering: stop venue streams, then drop the event receiver","Monitor channel-closed warnings as a signal of shutdown-order bugs"],"tags":["channel","messaging","shutdown","rust"],"backgroundTag":"broken-pipe","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"}