{"record":{"id":"2302b1f7ab905a9e","repo":"nautechsystems/nautilus_trader","slug":"system-event-sender-should-be-initialized-by-runne","errorCode":null,"errorMessage":"System event sender should be initialized by runner","messagePattern":"System event sender should be initialized by runner","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/live/runner.rs","lineNumber":82,"sourceCode":"/// Replaces the data event sender for the current thread.\npub fn replace_data_event_sender(sender: tokio::sync::mpsc::UnboundedSender<DataEvent>) {\n    DATA_EVENT_SENDER.with(|s| {\n        *s.borrow_mut() = Some(sender);\n    });\n}\n\n/// Gets the thread-local system event sender.\n///\n/// # Panics\n///\n/// Panics if the sender is uninitialized.\n#[must_use]\npub fn get_system_event_sender() -> tokio::sync::mpsc::UnboundedSender<SystemEvent> {\n    SYSTEM_EVENT_SENDER.with(|sender| {\n        sender\n            .borrow()\n            .as_ref()\n            .expect(\"System event sender should be initialized by runner\")\n            .clone()\n    })\n}\n\n/// Attempts to get the thread-local system 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_system_event_sender() -> Option<tokio::sync::mpsc::UnboundedSender<SystemEvent>> {\n    SYSTEM_EVENT_SENDER.with(|sender| sender.borrow().as_ref().cloned())\n}\n\n/// Sets the thread-local system event sender.\n///\n/// Can only be called once per thread.\n///\n/// # Panics\n///","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/live/runner.rs#L64-L100","documentation":"This panic comes from `get_system_event_sender()` in crates/common/src/live/runner.rs. It reads the thread-local `SYSTEM_EVENT_SENDER` slot that the live runner is expected to initialize; if it has not been set on the current thread, the expect panics. The sender is used to publish SystemEvents (e.g. state changes) from components to the runner's event loop.","triggerScenarios":"Calling `get_system_event_sender()` before the runner initialized the thread-local, from a different thread than the runner (thread-local miss), or in tests that exercise components without binding the runner channels.","commonSituations":"Components fetching the system sender during startup before `connect`/`bind_senders` ran; actor code moved to another tokio worker thread where the thread-local is unset; test harnesses calling publish paths without the runner's channel binding step.","solutions":["Initialize via the live runner (which binds SYSTEM_EVENT_SENDER) before any consumer calls this","Only call on the runner's thread; otherwise use `try_get_system_event_sender()` and handle the None case","Pass the sender explicitly through constructors where cross-thread access is needed","In tests, replicate the runner's channel binding before invoking code paths that publish system events"],"exampleFix":"// before\nlet sender = get_system_event_sender(); // panics if runner not initialized\n// after\nlet Some(sender) = try_get_system_event_sender() else {\n    anyhow::bail!(\"system event sender missing; ensure live runner initialized this thread\");\n};","handlingStrategy":"fallback","validationCode":"assert!(try_get_system_event_sender().is_some(), \"system sender must be bound by runner first\");","typeGuard":"fn system_sender_ready() -> bool { try_get_system_event_sender().is_some() }","tryCatchPattern":"let sender = try_get_system_event_sender().ok_or_else(|| anyhow!(\"system event sender not initialized\"))?;","preventionTips":["Bind runner channels before any component publishes system events","Keep publishing code on the runner's thread; pass senders explicitly for cross-thread use","Use try_get_* variant in startup paths with graceful failure"],"tags":["rust","panic","thread-local","live-runner","system-events"],"backgroundTag":"missing-env-var","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"}