{"record":{"id":"d0317b3c52daa517","repo":"nautechsystems/nautilus_trader","slug":"lighter-websocket-handler-failed-error","errorCode":null,"errorMessage":"Lighter WebSocket handler failed: {error}","messagePattern":"Lighter WebSocket handler failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/websocket/client.rs","lineNumber":439,"sourceCode":"            \"Lighter WebSocket initial connection cancelled\",\n        );\n\n        if self.is_active() {\n            log::warn!(\"Lighter WebSocket already connected\");\n            return Ok(());\n        }\n\n        if let Some(outcome) = finish_task(\n            &mut self.task_handle,\n            DISCONNECT_TIMEOUT,\n            DISCONNECT_TIMEOUT,\n        )\n        .await\n        {\n            match outcome {\n                TaskJoinOutcome::Completed(()) | TaskJoinOutcome::Aborted => {}\n                TaskJoinOutcome::Failed(error) => {\n                    anyhow::bail!(\"Lighter WebSocket handler failed: {error}\");\n                }\n                TaskJoinOutcome::Incomplete => {\n                    anyhow::bail!(\"Lighter WebSocket handler did not stop after abort\");\n                }\n            }\n        }\n\n        self.signal.store(false, Ordering::Release);\n        self.initial_connect_cancellation\n            .store(Arc::new(cancellation_token.clone()));\n\n        let (message_handler, raw_rx) = channel_epoch_message_handler();\n        let cfg = WebSocketConfig {\n            url: self.url.clone(),\n            headers: vec![],\n            heartbeat_interval_secs: Some(HEARTBEAT_INTERVAL.as_secs()),\n            heartbeat_payload: None,\n            connect_timeout_ms: Some(self.ws_timeout_secs.saturating_mul(1_000).max(1)),","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/websocket/client.rs#L421-L457","documentation":"This error is raised by connect_with_cancellation when the spawned Lighter WebSocket handler task terminates with an error while the initial connection is being established. The library joins the handler task after connecting and, if the join outcome is TaskJoinOutcome::Failed, the underlying error is propagated wrapped with this message. It indicates the background task that drives the WebSocket (read loop, auth, subscriptions) died during startup.","triggerScenarios":"Calling connect() (via connect_with_cancellation) when the freshly spawned WebSocket handler task returns Err before or during the join — e.g. the underlying websocket connection drops, authentication to Lighter fails inside the handler, or a stream yields an error immediately.","commonSituations":"Invalid API credentials passed to the Lighter credentials provider; network/proxy dropping the TCP connection right after the handshake; Lighter exchange-side rejection during subscribe/auth; an expired signing key configured in the adapter factory.","solutions":["Inspect the inner `{error}` in the message — it contains the root cause from the handler task; fix that underlying issue first.","Verify Lighter API key, secret and account index are correct and the key is active on the exchange.","Check network connectivity / proxy / firewall stability to Lighter's WebSocket endpoint; test with a simple wss client.","Enable debug logging (log::debug in the handler) to see what the handler task logged before failing.","Retry connect(); transient network failures resolve on reconnect, and the adapter's reconnect mechanism may also recover it."],"exampleFix":"// before: connect with wrong credentials\nlet client = factory.create(\"ws://mainnet.zklighter.elliot.ai/stream\", creds)?;\nclient.connect().await?; // Lighter WebSocket handler failed: auth rejected\n\n// after: verify credentials before connecting\nassert!(!creds.api_key.is_empty() && creds.account_index > 0);\nlet client = factory.create(\"wss://mainnet.zklighter.elliot.ai/stream\", creds)?;\nclient.connect().await?;","handlingStrategy":"try-catch","validationCode":"// preflight: verify endpoint reachability and credentials\nassert!(!creds.api_key.is_empty());\n// optionally ping the stream endpoint before connect","typeGuard":null,"tryCatchPattern":"match client.connect().await {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"handler failed\") => {\n        log::error!(\"handler error: {e:#}\"); // inspect inner cause\n        // retry with backoff\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Validate Lighter credentials before startup","Monitor network stability to the exchange endpoint","Log handler task errors at source for root-cause triage","Use the adapter's reconnect mechanism instead of manual reconnect loops"],"tags":["websocket","rust","network","async"],"backgroundTag":"connection-refused","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}