{"record":{"id":"16accd20e12f20cc","repo":"nautechsystems/nautilus_trader","slug":"execution-event-sender-should-be-initialized-by-ru","errorCode":null,"errorMessage":"Execution event sender should be initialized by runner","messagePattern":"Execution event sender should be initialized by runner","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/live/runner.rs","lineNumber":175,"sourceCode":"/// Replaces the system command sender for the current thread.\npub fn replace_system_command_sender(sender: tokio::sync::mpsc::UnboundedSender<SystemCommand>) {\n    SYSTEM_COMMAND_SENDER.with(|s| {\n        *s.borrow_mut() = Some(sender);\n    });\n}\n\n/// Gets the thread-local execution event sender.\n///\n/// # Panics\n///\n/// Panics if the sender is uninitialized.\n#[must_use]\npub fn get_exec_event_sender() -> tokio::sync::mpsc::UnboundedSender<ExecutionEvent> {\n    EXEC_EVENT_SENDER.with(|sender| {\n        sender\n            .borrow()\n            .as_ref()\n            .expect(\"Execution event sender should be initialized by runner\")\n            .clone()\n    })\n}\n\n/// Attempts to get the thread-local execution event sender without panicking.\n///\n/// Returns `None` if the sender is not initialized (e.g., in test environments).\n#[must_use]\npub fn try_get_exec_event_sender() -> Option<tokio::sync::mpsc::UnboundedSender<ExecutionEvent>> {\n    EXEC_EVENT_SENDER.with(|sender| sender.borrow().as_ref().cloned())\n}\n\n/// Sets the thread-local execution event sender.\n///\n/// Can only be called once per thread.\n///\n/// # Panics\n///","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/live/runner.rs#L157-L193","documentation":"`get_exec_event_sender` clones the thread-local tokio mpsc sender used to push ExecutionEvents from clients into the live runner. It panics with this message when EXEC_EVENT_SENDER has not been initialized by the runner on the current thread. This is an internal invariant: event-producing code (order submission, account state generation, position subscriptions) assumes the runner installed the channel.","triggerScenarios":"Calling `get_exec_event_sender()` or any wrapper (start, submit_order, submit_order_list_with_orders, generate_account_state, query_order, subscribe_positions) before the runner bound the exec-event channel on this thread.","commonSituations":"Bypassing `LiveNode::build()`/start; custom adapters emitting execution events in tests without binding a sender; running the emitting code on another thread than the one the runner initialized.","solutions":["Start the live runner (or call its sender-binding init) before any client/event-producing call","In tests, bind a test exec-event channel first (the pattern used by runner tests)","Keep event emission on the same OS thread where the runner initialized the thread-local","Use the non-panicking getter variant if the sender may legitimately be absent"],"exampleFix":"// before\nlet tx = get_exec_event_sender();\n// after\nrunner_bind_exec_sender(); // runner startup\nlet tx = get_exec_event_sender();","handlingStrategy":"validation","validationCode":"if !runner_senders_initialized() {\n    eprintln!(\"runner must initialize exec event sender first\");\n    return;\n}\nlet sender = get_exec_event_sender();","typeGuard":"fn exec_sender_ready() -> bool {\n    try_exec_event_sender().is_some()\n}","tryCatchPattern":"// Guard with the non-panicking getter\nif let Some(sender) = try_get_exec_event_sender() { /* emit event */ } else { init_runner(); }","preventionTips":["Bind the exec-event channel (runner start) before submitting orders or subscribing to positions","Prefer the non-panicking getter in adapter code where startup order may vary","Ensure event emission happens on the initializing thread","In test setups, install a test channel before exercising order/account APIs"],"tags":["rust","panic","thread-local","async","runner"],"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"}