nautechsystems/nautilus_trader · info · TransportError
initial WebSocket connection cancelled
Error message
initial WebSocket connection cancelled
What it means
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.
Source
Thrown at crates/network/src/websocket/client.rs:1006
biased;
() = cancellation_token.cancelled() => Err(initial_connect_cancelled()),
result = attempt => result,
}
}
fn initial_connect_retry_error(error: RetryError) -> TransportError {
let kind = match error {
RetryError::Canceled => return initial_connect_cancelled(),
RetryError::InvalidConfiguration { .. } => std::io::ErrorKind::InvalidInput,
RetryError::OperationTimeout { .. } | RetryError::ElapsedBudgetExceeded { .. } => {
std::io::ErrorKind::TimedOut
}
};
TransportError::Io(std::io::Error::new(kind, error))
}
fn initial_connect_cancelled() -> TransportError {
TransportError::Io(std::io::Error::new(
std::io::ErrorKind::Interrupted,
"initial WebSocket connection cancelled",
))
}
// Debug when we asked to disconnect (Disconnect/Closed), else Warn for a peer close
fn read_termination_log_level(connection_state: &AtomicU8) -> log::Level {
let mode = ConnectionMode::from_atomic(connection_state);
if mode.is_disconnect() || mode.is_closed() {
log::Level::Debug
} else {
log::Level::Warn
}
}
#[cfg(test)]
mod connection_error_tests {
use std::io;View on GitHub (pinned to 18893faf8b)
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
Example fix
// before
let conn = tokio::spawn(client.connect()); // aborted on shutdown -> cancelled
// after
let conn = tokio::select! {
res = client.connect() => res?,
_ = shutdown_token.cancelled() => return Ok(()), // handle cancellation explicitly
}; Defensive patterns
Strategy: try-catch
Validate before calling
// Check cancellation state before connecting
if cancel_token.is_cancelled() { /* skip connect */ } Type guard
fn is_cancelled(e: &TransportError) -> bool {
matches!(e, TransportError::Io(io) if io.kind() == std::io::ErrorKind::Interrupted)
} Try / catch
match client.connect().await {
Err(e) if is_cancelled(&e) => log::debug!("connect cancelled, shutting down"),
Err(e) => { /* retry or surface */ }
Ok(c) => { /* proceed */ }
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Binance Futures data teardown failed: {}
- Binance Spot data teardown failed: {}
- Lighter WebSocket handler failed: {error}
- Lighter WebSocket initial connection timeout after {} second
- Socket suffix cannot be empty: suffix is required for messag
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/72b92a20e0474614.
Report an issue: GitHub.