{"record":{"id":"8753598166641666","repo":"nautechsystems/nautilus_trader","slug":"failed-to-authenticate-websocket-session-e","errorCode":null,"errorMessage":"failed to authenticate WebSocket session: {e}","messagePattern":"failed to authenticate WebSocket session: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/adapters/deribit/src/execution.rs","lineNumber":555,"sourceCode":"        // Fetch initial account state\n        let account_state = self\n            .http_client\n            .request_account_state(self.core.account_id)\n            .await\n            .context(\"failed to request account state\")?;\n\n        self.emitter.send_account_state(account_state);\n\n        let session_result = async {\n            self.ws_client\n                .connect()\n                .await\n                .context(\"failed to connect WebSocket client for execution\")?;\n\n            self.ws_client\n                .authenticate_session(DERIBIT_EXECUTION_SESSION_NAME)\n                .await\n                .map_err(|e| anyhow::anyhow!(\"failed to authenticate WebSocket session: {e}\"))?;\n\n            log::debug!(\"WebSocket client authenticated for execution\");\n\n            // Subscribe to user order and trade updates for all instruments\n            self.ws_client\n                .subscribe_user_orders()\n                .await\n                .map_err(|e| anyhow::anyhow!(\"failed to subscribe to user orders: {e}\"))?;\n            self.ws_client\n                .subscribe_user_trades()\n                .await\n                .map_err(|e| anyhow::anyhow!(\"failed to subscribe to user trades: {e}\"))?;\n            self.ws_client\n                .subscribe_user_portfolio()\n                .await\n                .map_err(|e| anyhow::anyhow!(\"failed to subscribe to user portfolio: {e}\"))?;\n\n            if let Err(e) = self.ws_client.wait_for_subscriptions_confirmed(30.0).await {","sourceCodeStart":537,"sourceCodeEnd":573,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/deribit/src/execution.rs#L537-L573","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nlet client = DeribitExecutionClient::new(..., \"DERIBIT_API_KEY\", old_secret, ...);\n\n// after\nlet api_key = std::env::var(\"DERIBIT_TEST_API_KEY\").expect(\"missing key\");\nlet secret = std::env::var(\"DERIBIT_TEST_API_SECRET\").expect(\"missing secret\");\nassert_eq!(ws_url.host_str(), Some(\"test.deribit.com\"));\nlet client = DeribitExecutionClient::new(..., api_key, secret, ...);","handlingStrategy":"validation","validationCode":"fn validate_deribit_creds(env: &str) -> Result<(), String> {\n    let prefix = if env == \"test\" { \"DERIBIT_TEST\" } else { \"DERIBIT\" };\n    let key = std::env::var(format!(\"{prefix}_API_KEY\")).map_err(|_| \"missing API key\".to_string())?;\n    let secret = std::env::var(format!(\"{prefix}_API_SECRET\")).map_err(|_| \"missing secret\".to_string())?;\n    if key.trim() != key || key.is_empty() || secret.is_empty() {\n        return Err(\"key/secret empty or has whitespace\".into());\n    }\n    // Deribit auth is timestamp-sensitive\n    let skew = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap();\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = client.connect().await {\n    if e.to_string().contains(\"failed to authenticate WebSocket session\") {\n        // surface the inner Deribit error and fail fast on bad credentials\n        log::error!(\"Deribit auth failed: {e:#}; check API key/secret, env (prod vs test), and clock sync\");\n        return Err(e);\n    }\n    return Err(e);\n}","preventionTips":["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."],"tags":["authentication","websocket","credentials","deribit"],"backgroundTag":"authentication-required","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}