{"record":{"id":"67ece42a7f818453","repo":"nautechsystems/nautilus_trader","slug":"failed-to-request-logging-sync-e","errorCode":null,"errorMessage":"failed to request logging sync: {e}","messagePattern":"failed to request logging sync: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/logging/logger.rs","lineNumber":1315,"sourceCode":"        let lifecycle = LOGGER_LIFECYCLE.lock();\n\n        if *lifecycle != LoggerLifecycle::Running {\n            return Ok(());\n        }\n\n        let Some(tx) = LOGGER_TX.get() else {\n            anyhow::bail!(\"Logging is running without a published sender\");\n        };\n\n        sync_sender_to_disk(tx)\n    }\n}\n\n#[cfg(not(all(feature = \"simulation\", madsim)))]\nfn sync_sender_to_disk(tx: &std::sync::mpsc::Sender<LogEvent>) -> anyhow::Result<()> {\n    let (done_tx, done_rx) = std::sync::mpsc::channel();\n    tx.send(LogEvent::Sync(done_tx))\n        .map_err(|e| anyhow::anyhow!(\"failed to request logging sync: {e}\"))?;\n\n    done_rx\n        .recv()\n        .map_err(|e| anyhow::anyhow!(\"failed to receive logging sync acknowledgement: {e}\"))?\n}\n\n/// Logs a message with the given level, color, and component.\npub fn log<T: AsRef<str>>(level: LogLevel, color: LogColor, component: Ustr, message: T) {\n    let color = Value::from(color as u8);\n\n    match level {\n        LogLevel::Off => {}\n        LogLevel::Trace => {\n            log::trace!(component = component.to_value(), color = color; \"{}\", message.as_ref());\n        }\n        LogLevel::Debug => {\n            log::debug!(component = component.to_value(), color = color; \"{}\", message.as_ref());\n        }","sourceCodeStart":1297,"sourceCodeEnd":1333,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/logging/logger.rs#L1297-L1333","documentation":"`sync_sender_to_disk` sends a `LogEvent::Sync` oneshot handshake to the logger thread to flush buffered log events, then waits for the acknowledgement. If the `tx.send` fails — meaning the logging thread's receiver was dropped (logger thread exited/shut down) or the channel is broken — this error is returned.","triggerScenarios":"Calling flush/sync (logger flush API or guard drop-time flush) after the logging thread has already terminated: guard dropped while another reference triggers flush, logger thread panicked, or flush invoked during shutdown ordering races.","commonSituations":"Calling logger.flush() after shutdown/exit handlers ran; dropping the LogGuard then flushing from another thread; panics in the logging thread from malformed events; multi-node processes where one node's teardown closed the shared sender.","solutions":["Ensure the LogGuard outlives all flush calls; flush before dropping the guard.","Treat send-failure as 'logging already shut down' — handle gracefully and skip flushing instead of propagating.","Check whether the logging thread panicked (look for earlier panics) and fix the event payload or sink that caused it.","Sequence shutdown: flush logs first, then drop guard, then exit; avoid flushing from atexit/Destructor after teardown."],"exampleFix":"// before\ndrop(guard);\nlogger.flush()?; // failed to request logging sync\n// after\nguard.flush()?; // flush while logging thread is alive\n// then\ndrop(guard);","handlingStrategy":"try-catch","validationCode":"// Rust: confirm the logging thread is alive before flushing\nif !logging_thread_running() { return Ok(()); } // nothing to flush","typeGuard":"fn can_flush(tx: &Sender<LogEvent>) -> bool { !tx.is_closed() } // wrapper with capacity probe","tryCatchPattern":"match sync_sender_to_disk(&tx) {\n    Err(e) if e.to_string().contains(\"failed to request logging sync\") => {\n        debug!(\"logger already shut down; skipping flush\");\n    }\n    other => other?,\n}","preventionTips":["Flush logs before dropping the LogGuard, while the logger thread is alive.","Order shutdown explicitly: flush -> drop guard -> process exit.","Avoid flushing from atexit/destructors or other threads after teardown.","Investigate logger-thread panics; a dead thread makes every later flush fail."],"tags":["rust","logging","channel","shutdown"],"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"}