{"record":{"id":"5252b1f7dc9bf0cb","repo":"nautechsystems/nautilus_trader","slug":"failed-to-send-update-command-e-5252b1","errorCode":null,"errorMessage":"Failed to send update command: {e}","messagePattern":"Failed to send update command: (.+?)","errorType":"exception","errorClass":"TransportError","httpStatus":null,"severity":"error","filePath":"crates/network/src/websocket/client.rs","lineNumber":1348,"sourceCode":"                std::io::ErrorKind::TimedOut,\n                format!(\n                    \"reconnection timed out after {}s\",\n                    self.connect_timeout.as_secs_f64()\n                ),\n            ))\n        })??;\n\n        if ConnectionMode::from_atomic(&self.connection_mode).is_disconnect() {\n            log::debug!(\"Reconnect aborted mid-flight (after connect)\");\n            return Ok(ReconnectOutcome::Aborted);\n        }\n\n        // Use a oneshot channel to synchronize the writer swap before transitioning\n        // back to ACTIVE. Buffered messages stay in the writer task and replay later.\n        let (tx, rx) = tokio::sync::oneshot::channel();\n        if let Err(e) = self.writer_tx.send(WriterCommand::Update(new_writer, tx)) {\n            log::error!(\"{e}\");\n            return Err(TransportError::Io(std::io::Error::new(\n                std::io::ErrorKind::BrokenPipe,\n                format!(\"Failed to send update command: {e}\"),\n            )));\n        }\n\n        // Wait for writer to confirm it accepted the new socket\n        let connection_epoch = match rx.await {\n            Ok(connection_epoch) => {\n                log::debug!(\"Writer confirmed socket update: epoch={connection_epoch}\");\n                connection_epoch\n            }\n            Err(e) => {\n                log::error!(\"Writer dropped update channel: {e}\");\n                return Err(TransportError::Io(std::io::Error::new(\n                    std::io::ErrorKind::BrokenPipe,\n                    \"Writer task dropped response channel\",\n                )));\n            }","sourceCodeStart":1330,"sourceCodeEnd":1366,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/websocket/client.rs#L1330-L1366","documentation":"After a reconnect establishes a new socket, the client sends a WriterCommand::Update to the writer task over an mpsc channel so it can swap in the new writer before the state machine returns to ACTIVE. If the writer task has already exited (its receiver dropped), the send fails and this BrokenPipe TransportError is returned. It means the internal writer task is gone, so the reconnect cannot complete through the normal path.","triggerScenarios":"writer_tx.send(WriterCommand::Update(..)) failing because the writer task was aborted, panicked, or its loop exited (e.g. after an earlier disconnect or fatal send error) while reconnect_with_outcome was in progress.","commonSituations":"Writer task killed by an unrelated panic during a network blip; client shutting down concurrently with reconnect; a prior unrecoverable writer error ended the task but reconnect was still attempted.","solutions":["Log and inspect writer-task lifetime; ensure the writer loop only exits on deliberate shutdown commands","Retry the reconnect from scratch (recreate client/writer) rather than reusing a half-dead client instance","Check writer task code for panics (e.g. on poisoned locks) and make the loop resilient to transient socket errors","If shutdown is concurrent with reconnect, gate reconnect on a connection-state check"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_broken_pipe(e: &TransportError) -> bool {\n    matches!(e, TransportError::Io(io) if io.kind() == std::io::ErrorKind::BrokenPipe)\n}","tryCatchPattern":"match reconnect_with_outcome().await {\n    Err(e) if is_broken_pipe(&e) => {\n        // writer task dead: rebuild client or rerun full connect\n        rebuild_and_connect().await?;\n    }\n    r => r?,\n}","preventionTips":["Keep the writer task resilient: never panic on transient socket errors","Ensure the writer loop exits only on deliberate shutdown commands","Avoid racing disconnect/shutdown against reconnect on the same client"],"tags":["network","websocket","broken-pipe","internal-task","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-14T05:17:10.506Z"}