nautechsystems/nautilus_trader · error · anyhow::Error

failed to send RTDS {action} request: {e}

Error message

failed to send RTDS {action} request: {e}

What it means

The RTDS client sends subscription/request payloads over the WebSocket via ws.send_text; when the send fails, it wraps the underlying WebSocketClient error as 'failed to send RTDS {action} request: {e}'. It means the control-plane message for the given action (e.g. subscribe/auth) never reached Polymarket's RTDS gateway.

Source

Thrown at crates/adapters/polymarket/src/rtds.rs:1099

    async fn send_wire_request(
        &self,
        ws: &Arc<WebSocketClient>,
        action: &'static str,
        subscriptions: Vec<RtdsWireSubscription>,
    ) -> anyhow::Result<()> {
        if subscriptions.is_empty() {
            return Ok(());
        }

        let request = RtdsWireRequest {
            action,
            subscriptions,
        };
        let payload = serde_json::to_string(&request)?;
        ws.send_text(payload, None)
            .await
            .map_err(|e| anyhow::anyhow!("failed to send RTDS {action} request: {e}"))
    }

    async fn run_message_loop(
        &self,
        ws: Arc<WebSocketClient>,
        mut raw_rx: tokio::sync::mpsc::UnboundedReceiver<Message>,
    ) {
        loop {
            match raw_rx.recv().await {
                Some(Message::Text(text)) => {
                    if text.as_str() == RECONNECTED {
                        log::info!("Polymarket RTDS reconnected");
                        self.request_reconcile(ReconcileReason::TransportReset);
                        continue;
                    }

                    if text.as_str() == "PONG" {
                        continue;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Retry after the connection is re-established; RTDS reconnect logic typically resubscribes automatically
  2. Check the inner error (after ': {e}') to distinguish closed socket vs write failure
  3. Verify the RTDS endpoint is reachable and the socket is connected before sending requests
  4. Inspect auth state — servers often close sockets after auth expiry, making the next send fail

Example fix

// before
ws.send_text(payload, None).await?;
// after
if !ws.is_connected() { reconnect().await?; }
ws.send_text(payload, None).await
    .map_err(|e| { warn!("RTDS {action} send failed: {e:#}"); e })?;
Defensive patterns

Strategy: retry

Try / catch

// Rust
match send_rtds_request(action, subscriptions).await {
    Err(e) if e.to_string().contains("failed to send RTDS") => {
        reconnect().await?;
        send_rtds_request(action, subscriptions).await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling the RTDS request-sending path while the WebSocket connection is closed, dropped, or the outbound channel is full/closed — the serde_json::to_string of the request succeeded but transport failed.

Common situations: Network outage mid-session, server closing the socket after auth failure, attempting to (re)subscribe on a dead connection, or sending before the connection handshake finished.

Related errors


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