nautechsystems/nautilus_trader · error

failed to subscribe to user orders: {e}

Error message

failed to subscribe to user orders: {e}

What it means

Raised in `DeribitExecutionClient::connect` after WebSocket authentication succeeds, when the `private` channel subscription for user order updates fails. The client maps the underlying ws-client error into an anyhow error and aborts connect, since order fills/updates would otherwise be silently missed. This is a fatal setup error for an execution client: without the user-orders channel the adapter cannot track order state.

Source

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

        let session_result = async {
            self.ws_client
                .connect()
                .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");

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check connect logs for the inner `{e}` detail from the ws client to see the actual JSON-RPC failure reason.
  2. Verify API key/secret are valid, active, and scoped for the chosen environment (testnet vs production) before connecting.
  3. Ensure network connectivity/proxy/firewall allows a persistent wss connection to the Deribit endpoint.
  4. Reconnect the underlying WebSocket (or recreate the client) and retry connect; connect is re-runnable after the rollback path resets subscription state.
  5. Check Deribit rate limits / subscription quotas if many clients subscribe concurrently.

Example fix

// before
let client = DeribitExecutionClient::new(...);
client.connect().await?; // may fail: failed to subscribe to user orders

// after
for attempt in 1..=3 {
    match client.connect().await {
        Ok(()) => break,
        Err(e) if e.to_string().contains("failed to subscribe") && attempt < 3 => {
            tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await;
        }
        Err(e) => return Err(e),
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// before connect
assert!(api_key.is_some() && api_secret.is_some(), "Deribit credentials required");
assert!(ws_endpoint_is_reachable(&url).await, "Deribit ws endpoint unreachable");

Try / catch

// Rust
match client.connect().await {
    Err(e) if format!("{e:#}").contains("failed to subscribe to user orders") => {
        // log inner cause, backoff, retry connect
    }
    Err(e) => return Err(e),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Calling `connect()` on a DeribitExecutionClient where `ws_client.subscribe_user_orders().await` returns Err — e.g. the underlying JSON-RPC `private/subscribe` to `user.orders.*` channels is rejected, the session dropped mid-request, the network failed, or the ws client was already closed.

Common situations: Expired or partially-scoped Deribit API credentials where private subscriptions are rejected; network/proxy drops between auth and subscribe; attempting to connect while the WebSocket is disconnected or reconnecting; testnet/mainnet URL misconfiguration; rate-limit rejection of the subscribe RPC.

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/581705dea8f3dbfa. Report an issue: GitHub.