nautechsystems/nautilus_trader · error

failed to subscribe to user trades: {e}

Error message

failed to subscribe to user trades: {e}

What it means

Raised in `DeribitExecutionClient::connect` when the private-channel subscription for user trades (`subscribe_user_trades`) fails, after user-orders subscription succeeded. The connect sequence aborts because trade/fill updates are required for accurate position and execution reporting. The inner ws-client error is embedded in the message via `{e}`.

Source

Thrown at crates/adapters/deribit/src/execution.rs:567

                .await
                .context("failed to connect WebSocket client for execution")?;

            self.ws_client
                .authenticate_session(DERIBIT_EXECUTION_SESSION_NAME)
                .await
                .map_err(|e| anyhow::anyhow!("failed to authenticate WebSocket session: {e}"))?;

            log::debug!("WebSocket client authenticated for execution");

            // Subscribe to user order and trade updates for all instruments
            self.ws_client
                .subscribe_user_orders()
                .await
                .map_err(|e| anyhow::anyhow!("failed to subscribe to user orders: {e}"))?;
            self.ws_client
                .subscribe_user_trades()
                .await
                .map_err(|e| anyhow::anyhow!("failed to subscribe to user trades: {e}"))?;
            self.ws_client
                .subscribe_user_portfolio()
                .await
                .map_err(|e| anyhow::anyhow!("failed to subscribe to user portfolio: {e}"))?;

            if let Err(e) = self.ws_client.wait_for_subscriptions_confirmed(30.0).await {
                // Roll back subscription state so a retry re-sends subscribe requests
                let _ = self.ws_client.unsubscribe_user_orders().await;
                let _ = self.ws_client.unsubscribe_user_trades().await;
                let _ = self.ws_client.unsubscribe_user_portfolio().await;
                anyhow::bail!("subscription confirmation failed: {e}");
            }

            log::debug!("Subscribed to user order, trade, and portfolio updates");

            // Spawn stream handler to dispatch WebSocket messages to the execution engine
            let stream = self.ws_client.stream()?;
            self.spawn_stream_handler(stream)?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the wrapped `{e}` for the concrete JSON-RPC or transport error.
  2. Retry connect; the client's rollback path unsubscribes all user channels so a retry re-sends the full subscription set.
  3. Re-validate credentials/session — an invalid or expired session can pass one RPC and fail the next.
  4. Stabilize the network path (keepalive, disable aggressive proxy idle timeouts) so the handshake completes atomically.
  5. If quota-related, reduce concurrent private subscriptions or clients per API key.
Defensive patterns

Strategy: retry

Try / catch

// Retry the whole connect sequence so all three user subscriptions are re-sent atomically
if let Err(e) = client.connect().await {
    tracing::warn!("connect failed: {e:#}; retrying with backoff");
    backoff_retry(|| client.connect()).await?;
}

Prevention

When it happens

Trigger: Calling `connect()` where `subscribe_user_orders()` succeeds but `ws_client.subscribe_user_orders().await` for trades returns Err — e.g. connection drops between the two subscribe RPCs, the trades channel `private/subscribe` request is rejected, or the session token became invalid mid-connect.

Common situations: Flaky connections where the first subscribe succeeds and the second fails; auth token expiry/refresh failure between RPCs; Deribit rejecting the channel name or quota; proxies that kill the socket during the multi-request handshake.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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