{"record":{"id":"389756aad4027842","repo":"nautechsystems/nautilus_trader","slug":"l3-websocket-failed-to-authenticate-e","errorCode":null,"errorMessage":"L3 WebSocket failed to authenticate: {e}","messagePattern":"L3 WebSocket failed to authenticate: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/kraken/src/data/spot.rs","lineNumber":351,"sourceCode":"            self.l3_handler_task = self.spawn_l3_handler_task(ws_l3, true);\n        }\n\n        let ws_l3 = self\n            .ws_l3\n            .as_ref()\n            .expect(\"ws_l3 initialized above\")\n            .clone();\n\n        self.spawn_ws(\n            async move {\n                ws_l3\n                    .wait_until_active(10.0)\n                    .await\n                    .map_err(|e| anyhow::anyhow!(\"L3 WebSocket failed to become active: {e}\"))?;\n                ws_l3\n                    .wait_until_authenticated(10.0)\n                    .await\n                    .map_err(|e| anyhow::anyhow!(\"L3 WebSocket failed to authenticate: {e}\"))?;\n                ws_l3\n                    .subscribe_book_l3(symbol_ustr, depth)\n                    .await\n                    .map_err(|e| anyhow::anyhow!(\"{e}\"))\n            },\n            \"subscribe l3 book\",\n        );\n\n        Ok(())\n    }\n\n    fn spawn_l3_handler_task(\n        &self,\n        handler_client: KrakenSpotWebSocketClient,\n        restart: bool,\n    ) -> Option<TaskRef> {\n        let data_sender = self.data_sender.clone();\n        let instruments = self.instruments.clone();","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/kraken/src/data/spot.rs#L333-L369","documentation":"After the L3 WebSocket becomes active, subscribe_l3_book requires it to be authenticated (L3 order books on Kraken Spot v2 need API credentials). `wait_until_authenticated(10.0)` waits on the auth tracker for 10 seconds and returns `KrakenWsError::AuthenticationError(\"Authentication not completed within 10 seconds\")` on timeout or explicit auth failure; the adapter re-wraps it with this message.","triggerScenarios":"Calling subscribe_book_deltas when the L3 client's authenticate() fails or never completes within 10s: invalid/expired API key or secret, Kraken REST auth-token endpoint unreachable, wrong passphrase/permissions on the key, or credentials absent (though the client bails earlier in that case).","commonSituations":"Misconfigured or rotated Kraken API keys; key lacks the required permissions; IP allowlist on the key excludes this server; REST endpoint for token refresh blocked by firewall; slow network making the token exchange exceed 10s.","solutions":["Verify the configured api_key/api_secret are valid, active, and have the required Kraken permissions.","Check that the server's IP is allowlisted for the Kraken API key if key IP restrictions are enabled.","Test the Kraken auth token REST endpoint reachability from this machine (it is called by refresh_auth_token before the WS auth).","Check logs for the L3 handler task's 'L3 WebSocket authentication failed' line to see the underlying auth error.","Retry after confirming credentials; if the timeout is marginal due to latency, reduce network latency or file an issue to raise the fixed 10s window."],"exampleFix":"// before (config with invalid creds)\nKrakenDataClientConfig::new(api_key, api_secret)\n// after — verify credentials work before subscribing\nlet client = reqwest::Client::new();\n// ensure the REST auth-token call succeeds with these credentials first\nassert!(refresh_auth_token(&config).await.is_ok(), \"invalid Kraken API credentials\");\ndata_client.subscribe_book_deltas(&cmd)?;","handlingStrategy":"validation","validationCode":"// fail fast before subscribing if credentials are absent\nif !config.has_api_credentials() {\n    anyhow::bail!(\"L3 order book requires API credentials; configure api_key and api_secret\");\n}\n// optionally validate credentials via a REST token refresh before subscribing\nrefresh_auth_token(&config).await?;","typeGuard":null,"tryCatchPattern":"match client.subscribe_book_deltas(&cmd) {\n    Err(e) if e.to_string().contains(\"failed to authenticate\") => {\n        // verify/rotate Kraken API keys, check IP allowlist, then retry\n        eprintln!(\"Kraken L3 auth failed: {e}; check API key validity and permissions\");\n    }\n    Err(e) => return Err(e),\n    Ok(()) => {}\n}","preventionTips":["Validate Kraken API keys and permissions whenever they are rotated or deployed to a new host","Keep the key's IP allowlist in sync with the server's egress IP","Ensure the Kraken REST auth-token endpoint is reachable from the deployment environment","Pre-check has_api_credentials before requesting L3 data"],"tags":["websocket","kraken","authentication","credentials","timeout"],"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"}