nautechsystems/nautilus_trader · error
Stream receiver already taken or not connected
Error message
Stream receiver already taken or not connected
What it means
BitmexWebSocketClient::stream() hands out the sole message receiver via Option::take on self.out_rx. The field is None when the websocket is not connected or when a previous stream() call already consumed the receiver, in which case the expect panics. The Arc::try_unwrap right after enforces that no cloned client still shares the receiver.
Source
Thrown at crates/adapters/bitmex/src/websocket/client.rs:643
"WebSocket connection timeout after {timeout_secs} seconds"
))
})?;
Ok(())
}
/// Provides the internal stream as a channel-based stream.
///
/// # Panics
///
/// This function panics:
/// - If the websocket is not connected.
/// - If `stream` has already been called somewhere else (stream receiver is then taken).
pub fn stream(&mut self) -> impl Stream<Item = BitmexWsMessage> + use<> {
let rx = self
.out_rx
.take()
.expect("Stream receiver already taken or not connected");
let mut rx = Arc::try_unwrap(rx).expect("Cannot take ownership - other references exist");
async_stream::stream! {
while let Some(msg) = rx.recv().await {
yield msg;
}
}
}
/// Closes the client.
///
/// # Errors
///
/// Returns an error if the WebSocket is not connected or if closing fails.
pub async fn close(&mut self) -> Result<(), BitmexWsError> {
log::debug!("Starting close process");
self.signal.store(true, Ordering::Relaxed);
View on GitHub (pinned to 18893faf8b)
Solutions
- Call stream() exactly once, after connect(), and treat the returned stream as the sole consumer for that connection.
- On any reconnect, build a new BitmexWebSocketClient (connect then stream) rather than re-streaming the old instance.
- Route messages to multiple consumers yourself via an mpsc/broadcast channel fed from the single stream.
- Before calling, ensure no clone of the client survives, otherwise the subsequent Arc::try_unwrap expect will panic too.
Example fix
// before client.connect().await?; let s1 = client.stream(); // after stream end, on the same client: let s2 = client.stream(); // panics: receiver already taken // after client.connect().await?; let s1 = client.stream(); // for a new stream: create a fresh client, connect, then stream once
Defensive patterns
Strategy: validation
Validate before calling
// Enforce connect-then-single-stream usage with your own state
enum WsState { Disconnected, Connected(bool) } // bool = stream taken
fn take_stream(client: &mut BitmexWebSocketClient, st: &mut WsState)
-> Result<impl Stream<Item = BitmexWsMessage>, String> {
match st { WsState::Connected(false) => { *st = WsState::Connected(true); Ok(client.stream()) },
_ => Err("connect() first and stream() only once".to_string()) }
} Prevention
- Call connect() before stream(), and stream() exactly once per connection.
- Handle stream termination by rebuilding the client, not by re-calling stream().
- Avoid cloning the client; distribute messages downstream with channels.
When it happens
Trigger: Calling stream() before connect(); calling stream() twice on the same BitmexWebSocketClient; the first stream's consumer having already taken ownership while another caller retries stream().
Common situations: Resubscribing after a stream error by calling stream() again on the same client; both a market-data actor and a logging task attempting to consume Bitmex messages; supervisor loops that recreate the stream after a drop without reconnecting.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Stream receiver already taken or client not connected - stre
- Stream receiver already taken or client not connected - stre
- Message stream receiver already taken or not connected
- InstrumentState channel requires kind and currency parameter
- Both `api_key` and `api_secret` must be provided together
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/16da6cb191c76206.
Report an issue: GitHub.