{"record":{"id":"23fda5699a0cf28a","repo":"Kuberwastaken/claurst","slug":"websocket-closed-by-chrome","errorCode":null,"errorMessage":"WebSocket closed by Chrome","messagePattern":"WebSocket closed by Chrome","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-rust/crates/commands/src/chrome.rs","lineNumber":75,"sourceCode":"        ws: &mut WebSocketStream<MaybeTlsStream<TcpStream>>,\r\n        method: &str,\r\n        params: Value,\r\n    ) -> anyhow::Result<Value> {\r\n        let id = next_id();\r\n        let request = json!({ \"id\": id, \"method\": method, \"params\": params });\r\n        ws.send(WsMessage::Text(request.to_string())).await?;\r\n\r\n        // Drain messages until we get the one with our id (ignore events).\r\n        loop {\r\n            let raw = ws\r\n                .next()\r\n                .await\r\n                .ok_or_else(|| anyhow::anyhow!(\"WebSocket closed unexpectedly\"))??;\r\n            let text: String = match raw {\r\n                WsMessage::Text(t) => t.to_string(),\r\n                WsMessage::Ping(_) | WsMessage::Pong(_) => continue,\r\n                WsMessage::Close(_) => {\r\n                    return Err(anyhow::anyhow!(\"WebSocket closed by Chrome\"));\r\n                }\r\n                _ => continue,\r\n            };\r\n            let val: Value = serde_json::from_str(&text)?;\r\n            if val[\"id\"] == id {\r\n                if let Some(err) = val.get(\"error\") {\r\n                    return Err(anyhow::anyhow!(\"CDP error: {}\", err));\r\n                }\r\n                return Ok(val);\r\n            }\r\n            // It's an event or different response — keep waiting.\r\n        }\r\n    }\r\n\r\n    // -----------------------------------------------------------------------\r\n    // Session take/restore helpers\r\n    //\r\n    // We avoid holding a MutexGuard across await points by taking ownership\r","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/commands/src/chrome.rs#L57-L93","documentation":"cdp_call received an explicit WebSocket Close frame while waiting for the CDP response. Unlike a silent stream end, Chrome actively closed the DevTools WebSocket connection. The library converts this into an anyhow error since the pending command can never complete.","triggerScenarios":"In the match on WsMessage inside cdp_call's drain loop, a Close(_) frame arrives before the response with the matching id: Chrome closed the socket (tab closed, browser exiting, target destroyed, or CDP session detached).","commonSituations":"User or automation closed the browser/tab during a command; Chrome crashed; the debugging session was invalidated by navigation that destroyed the target; timeout-based detachment by Chrome DevTools protocol.","solutions":["Reconnect to Chrome's debug WebSocket and re-issue the command.","Keep the target tab open for the duration of the automation session.","Check Chrome's stderr/logs for crashes; increase stability (disable extensions, use a fresh profile).","List available targets via http://localhost:9222/json and connect to an existing page target."],"exampleFix":"// before\nWsMessage::Close(_) => return Err(anyhow::anyhow!(\"WebSocket closed by Chrome\")),\n// after\nWsMessage::Close(frame) => {\n    return Err(anyhow::anyhow!(\"WebSocket closed by Chrome: {:?}\", frame.map(|f| f.code)));\n}","handlingStrategy":"fallback","validationCode":"// confirm the target still exists before sending commands\nlet targets: Vec<Value> = reqwest::get(\"http://localhost:9222/json\").await?.json().await?;\nif !targets.iter().any(|t| t[\"id\"] == target_id) {\n    bail!(\"target {} no longer exists\", target_id);\n}","typeGuard":null,"tryCatchPattern":"// on close, reconnect and re-attach to a live target\nif let Err(e) = cdp_call(&mut ws, method, params).await {\n    if e.to_string().contains(\"closed by Chrome\") {\n        let ws = connect_to_live_target().await?;\n        return cdp_call(ws, method, params).await;\n    }\n    return Err(e);\n}","preventionTips":["Launch a dedicated Chrome instance for automation and keep it open","Re-list targets after any navigation that may destroy the page","Watch Chrome logs for crashes; use a clean profile without extensions"],"tags":["websocket","chrome","cdp","connection"],"backgroundTag":"websocket-closed-unexpectedly","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}