nautechsystems/nautilus_trader · error · anyhow::Error

WebSocket message receiver not available

Error message

WebSocket message receiver not available

What it means

`start_ws_stream` connects the Polymarket WebSocket client then calls `take_message_receiver()` to obtain the mpsc receiver for incoming messages. If the client cannot produce a receiver (connection not fully established, already taken, or client in a bad state), it returns this error. If the rollback `disconnect()` also fails, the disconnect failure is attached as context.

Source

Thrown at crates/adapters/polymarket/src/execution/lifecycle.rs:289

            .await
            .context("failed to connect user WebSocket")?;

        if let Err(e) = self
            .ws_client
            .subscribe_user()
            .await
            .context("failed to subscribe to user channel")
        {
            if let Err(shutdown_error) = self.ws_client.disconnect().await {
                return Err(e.context(format!(
                    "Polymarket WebSocket startup rollback failed: {shutdown_error}"
                )));
            }
            return Err(e);
        }

        let Some(mut rx) = self.ws_client.take_message_receiver() else {
            let receiver_error = anyhow::anyhow!("WebSocket message receiver not available");
            if let Err(shutdown_error) = self.ws_client.disconnect().await {
                return Err(receiver_error.context(format!(
                    "Polymarket WebSocket startup rollback failed: {shutdown_error}"
                )));
            }
            return Err(receiver_error);
        };

        let emitter = self.emitter.clone();
        let token_instruments = self.shared_token_instruments.clone();
        let account_id = self.core.account_id;
        let http_client = self.http_client.clone();
        let clock = self.clock;
        let signature_type = self.config.signature_type;
        let stopping = self.stopping.clone();
        let user_address = self
            .secrets
            .funder

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure teardown_partial_connect/teardown completes before reconnecting so a fresh ws_client/receiver is available
  2. Check that connect_client is not invoked twice on the same client instance concurrently
  3. Inspect the 'startup rollback failed' context to see if disconnect also errored, indicating a deeper client-state problem
  4. Recreate/rebuild the execution client if its WS state is irrecoverably inconsistent

Example fix

// before: reconnect without teardown
adapter.connect().await?; // receiver already taken
// after: tear down previous session first
adapter.teardown_partial_connect().await;
adapter.connect().await?;
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure no prior session holds the receiver
if adapter.is_connected() {
    adapter.teardown_partial_connect().await;
}

Try / catch

match adapter.connect().await {
    Err(e) if e.to_string().contains("receiver not available") => {
        adapter.teardown_partial_connect().await;
        adapter.connect().await?; // retry once on clean state
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling connect_client when the WS handshake completed at the transport level but the client exposes no message receiver — e.g. the receiver was already taken by a prior connection attempt, or take_message_receiver is only valid exactly once per connection.

Common situations: Double-connecting an execution client without tearing down the previous session; a partially failed previous connect left the ws_client in an inconsistent state; connecting the same client from two code paths concurrently.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/19df7e4a828f95ea. Report an issue: GitHub.