nautechsystems/nautilus_trader · error
subscription confirmation failed: {e}
Error message
subscription confirmation failed: {e} What it means
The Deribit execution client subscribes to user order, trade, and portfolio channels during connect; this error is raised when the WebSocket client does not receive subscription confirmations within the 30-second timeout. On failure it unsubscribes from all three channels so a reconnect retry re-sends the subscribe requests cleanly.
Source
Thrown at crates/adapters/deribit/src/execution.rs:578
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)?;
Ok::<(), anyhow::Error>(())
}
.await;
if let Err(e) = session_result {
if let Err(teardown_error) = self.teardown_partial_connect().await {
return Err(e.context(format!(
"Deribit execution startup teardown failed: {teardown_error}"
)));
}View on GitHub (pinned to 18893faf8b)
Solutions
- Verify Deribit API credentials are valid and test auth separately before connecting
- Check network connectivity and any proxy/firewall that may block or delay WebSocket frames
- Check Deribit status (outages/degraded service) and retry connect after unsubscribed rollback
- Increase tolerance by retrying connect — subscription state is rolled back so a retry re-subscribes correctly
Example fix
// before
let client = DeribitExecutionClient::new(...); // connect() may bail on confirmation timeout
client.connect().await?;
// after
for attempt in 0..3 {
match client.connect().await {
Ok(()) => break,
Err(e) if e.to_string().contains("subscription confirmation failed") && attempt < 2 => {
log::warn!("retrying connect after subscription failure: {e}");
tokio::time::sleep(Duration::from_secs(5)).await;
}
Err(e) => return Err(e),
}
} Defensive patterns
Strategy: retry
Validate before calling
// Before connecting, verify credentials and reachability
let creds = std::env::var("DERIBIT_API_KEY")?;
assert!(!creds.is_empty());
// optionally ping Deribit REST: GET https://www.deribit.com/api/v2/public/test Try / catch
match client.connect().await {
Err(e) if e.to_string().contains("subscription confirmation failed") => retry_with_backoff(3),
other => other,
} Prevention
- Validate API credentials before connect so private channels subscribe successfully
- Monitor Deribit status pages and avoid connecting during known outages
- Keep connect retries with backoff — the client rolls back subscription state for clean retry
- Test WebSocket connectivity through any corporate proxy before production use
When it happens
Trigger: Calling connect when the Deribit WebSocket does not confirm all subscriptions (private/orders, private/trades, private/portfolio) within 30 seconds — typically due to network issues, slow Deribit API response, or failed authentication preventing private channel subscription.
Common situations: Deribit outage or degraded WebSocket service; expired API credentials so private channels are rejected; corporate proxy/firewall dropping or delaying WS frames; very slow network causing confirmation to arrive after the 30s window.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- failed to subscribe to user orders: {e}
- failed to subscribe to user trades: {e}
- failed to subscribe to user portfolio: {e}
- WS user data subscription timed out
- Lighter WebSocket initial connection timeout after {} second
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c58738261af7217a.
Report an issue: GitHub.