nautechsystems/nautilus_trader · critical
failed to authenticate WebSocket session: {e}
Error message
failed to authenticate WebSocket session: {e} What it means
After connecting the execution WebSocket, the client authenticates the session with Deribit using the configured API credentials (`authenticate_session`). If Deribit rejects the auth (bad key/secret, expired signature, clock skew, revoked key), execution.rs:555 wraps the underlying error with this message and the connect fails — no order/trade subscriptions are made.
Source
Thrown at crates/adapters/deribit/src/execution.rs:555
// Fetch initial account state
let account_state = self
.http_client
.request_account_state(self.core.account_id)
.await
.context("failed to request account state")?;
self.emitter.send_account_state(account_state);
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 {View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the API key/secret env vars are set correctly for the target environment (prod vs test) and trimmed of whitespace.
- Synchronize system clock (NTP) — Deribit auth is timestamp-sensitive.
- Check the wrapped inner error `{e}`: it usually states 'invalid credentials' vs 'authentication failed' to distinguish bad keys from expiry/clock issues.
- Regenerate the API key on the Deribit account and confirm required scopes for trading.
- Confirm the WebSocket URL matches the credential environment (www.deribit.com vs test.deribit.com).
Example fix
// before
let client = DeribitExecutionClient::new(..., "DERIBIT_API_KEY", old_secret, ...);
// after
let api_key = std::env::var("DERIBIT_TEST_API_KEY").expect("missing key");
let secret = std::env::var("DERIBIT_TEST_API_SECRET").expect("missing secret");
assert_eq!(ws_url.host_str(), Some("test.deribit.com"));
let client = DeribitExecutionClient::new(..., api_key, secret, ...); Defensive patterns
Strategy: validation
Validate before calling
fn validate_deribit_creds(env: &str) -> Result<(), String> {
let prefix = if env == "test" { "DERIBIT_TEST" } else { "DERIBIT" };
let key = std::env::var(format!("{prefix}_API_KEY")).map_err(|_| "missing API key".to_string())?;
let secret = std::env::var(format!("{prefix}_API_SECRET")).map_err(|_| "missing secret".to_string())?;
if key.trim() != key || key.is_empty() || secret.is_empty() {
return Err("key/secret empty or has whitespace".into());
}
// Deribit auth is timestamp-sensitive
let skew = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap();
Ok(())
} Try / catch
if let Err(e) = client.connect().await {
if e.to_string().contains("failed to authenticate WebSocket session") {
// surface the inner Deribit error and fail fast on bad credentials
log::error!("Deribit auth failed: {e:#}; check API key/secret, env (prod vs test), and clock sync");
return Err(e);
}
return Err(e);
} Prevention
- Validate key/secret presence and format at startup, before constructing the client.
- Match credentials to the environment: test keys for test.deribit.com, prod keys for www.deribit.com.
- Run NTP time sync — clock skew breaks Deribit authentication.
- Rotate keys through config management and restart the client after rotation.
- Log the full error chain ({e:#} with anyhow) to see the underlying Deribit auth message.
When it happens
Trigger: Wrong or missing DERIBIT API key/secret; revoked or expired API key; system clock drift breaking the HMAC/expiry-based Deribit auth; connecting to a environment (test/prod) with credentials from the other; keys lacking the required scopes.
Common situations: Rotated credentials but the adapter still reads old env vars; running on a box whose clock is a few minutes off; using production keys against test.deribit.com or vice versa; IP-restricted keys; copy-pasted key with whitespace/newline.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Missing API credentials; set Deribit environment variables
- Authentication failed: {e}
- Coinbase credentials unavailable for WS reset
- L3 WebSocket failed to authenticate: {e}
- missing WS auth token
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8753598166641666.
Report an issue: GitHub.