{"record":{"id":"72b92a20e0474614","repo":"nautechsystems/nautilus_trader","slug":"initial-websocket-connection-cancelled","errorCode":null,"errorMessage":"initial WebSocket connection cancelled","messagePattern":"initial WebSocket connection cancelled","errorType":"exception","errorClass":"TransportError","httpStatus":null,"severity":"info","filePath":"crates/network/src/websocket/client.rs","lineNumber":1006,"sourceCode":"        biased;\n        () = cancellation_token.cancelled() => Err(initial_connect_cancelled()),\n        result = attempt => result,\n    }\n}\n\nfn initial_connect_retry_error(error: RetryError) -> TransportError {\n    let kind = match error {\n        RetryError::Canceled => return initial_connect_cancelled(),\n        RetryError::InvalidConfiguration { .. } => std::io::ErrorKind::InvalidInput,\n        RetryError::OperationTimeout { .. } | RetryError::ElapsedBudgetExceeded { .. } => {\n            std::io::ErrorKind::TimedOut\n        }\n    };\n    TransportError::Io(std::io::Error::new(kind, error))\n}\n\nfn initial_connect_cancelled() -> TransportError {\n    TransportError::Io(std::io::Error::new(\n        std::io::ErrorKind::Interrupted,\n        \"initial WebSocket connection cancelled\",\n    ))\n}\n\n// Debug when we asked to disconnect (Disconnect/Closed), else Warn for a peer close\nfn read_termination_log_level(connection_state: &AtomicU8) -> log::Level {\n    let mode = ConnectionMode::from_atomic(connection_state);\n    if mode.is_disconnect() || mode.is_closed() {\n        log::Level::Debug\n    } else {\n        log::Level::Warn\n    }\n}\n\n#[cfg(test)]\nmod connection_error_tests {\n    use std::io;","sourceCodeStart":988,"sourceCodeEnd":1024,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/websocket/client.rs#L988-L1024","documentation":"This error is returned when an initial WebSocket connection attempt is cancelled, typically because the caller dropped the connect future or a cancellation token fired while the first connection was still being established. The library surfaces the cancellation as an io::Error with ErrorKind::Interrupted wrapped in TransportError so callers can distinguish deliberate cancellation from genuine connect failures. It is not a network fault; the handshake never completed because the operation was aborted.","triggerScenarios":"Calling WebSocketClient::connect and dropping the returned future or cancelling it via the CancellationToken before the handshake completes; task shutdown/timeout wrappers aborting initial_connect; initial_connect_retry_error propagating a cancelled retry loop.","commonSituations":"Graceful shutdown during app startup; a supervisor timing out slow cold-start connects and aborting the task; user navigation closing a client mid-connect; retry loop exhausted by cancellation rather than failure.","solutions":["Check whether your code (or a timeout wrapper) is aborting the connect future prematurely and extend the connect timeout if the abort is unintentional","Treat ErrorKind::Interrupted as benign shutdown and skip retry logic for it","If cancellation is intended, ensure shutdown paths handle this error quietly instead of logging it as a failure","Verify the CancellationToken is not dropped or cancelled while startup still needs the connection"],"exampleFix":"// before\nlet conn = tokio::spawn(client.connect()); // aborted on shutdown -> cancelled\n// after\nlet conn = tokio::select! {\n    res = client.connect() => res?,\n    _ = shutdown_token.cancelled() => return Ok(()), // handle cancellation explicitly\n};","handlingStrategy":"try-catch","validationCode":"// Check cancellation state before connecting\nif cancel_token.is_cancelled() { /* skip connect */ }","typeGuard":"fn is_cancelled(e: &TransportError) -> bool {\n    matches!(e, TransportError::Io(io) if io.kind() == std::io::ErrorKind::Interrupted)\n}","tryCatchPattern":"match client.connect().await {\n    Err(e) if is_cancelled(&e) => log::debug!(\"connect cancelled, shutting down\"),\n    Err(e) => { /* retry or surface */ }\n    Ok(c) => { /* proceed */ }\n}","preventionTips":["Never wrap connect in an abort-prone spawn without handling cancellation","Use tokio::select! with the shutdown token so cancellation is explicit","Size connect timeouts larger than any abort timeout you apply"],"tags":["network","websocket","cancellation","rust"],"backgroundTag":"websocket-connection-cancelled","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"}