{"record":{"id":"af0054678ff85b20","repo":"zeroclaw-labs/zeroclaw","slug":"qq-websocket-connection-closed-server-requested-r","errorCode":null,"errorMessage":"QQ WebSocket connection closed: server requested reconnect (resume will be attempted)","messagePattern":"QQ WebSocket connection closed: server requested reconnect \\(resume will be attempted\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/zeroclaw-channels/src/qq.rs","lineNumber":1779,"sourceCode":"                }\n            }\n        }\n\n        // Persist sequence number for potential resume on next reconnect\n        *self.last_sequence.write().await = if sequence >= 0 { Some(sequence) } else { None };\n\n        match exit_reason {\n            ExitReason::InvalidSession => {\n                // Clear stored session so next reconnect does a fresh Identify\n                *self.session_id.write().await = None;\n                *self.last_sequence.write().await = None;\n                anyhow::bail!(\n                    \"QQ WebSocket connection closed: invalid session (fresh auth required)\"\n                )\n            }\n            ExitReason::Reconnect => {\n                // Session state preserved — supervisor will reconnect and we'll attempt Resume\n                anyhow::bail!(\n                    \"QQ WebSocket connection closed: server requested reconnect (resume will be attempted)\"\n                )\n            }\n            ExitReason::Close(ref frame) => {\n                let (code, reason) = frame\n                    .as_ref()\n                    .map(|f| (f.code.to_string(), f.reason.to_string()))\n                    .unwrap_or_else(|| (\"unknown\".into(), \"none\".into()));\n                ::zeroclaw_log::record!(WARN, ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note).with_outcome(::zeroclaw_log::EventOutcome::Unknown).with_attrs(::serde_json::json!({\"code\": code.to_string(), \"reason\": reason.to_string()})), \"WebSocket closed with code=, reason=\\\"\\\"; resume will be attempted on reconnect\");\n                anyhow::bail!(\n                    \"QQ WebSocket connection closed: close_code={code}, reason=\\\"{reason}\\\"\"\n                )\n            }\n            ExitReason::StreamEnded => {\n                ::zeroclaw_log::record!(\n                    WARN,\n                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)\n                        .with_outcome(::zeroclaw_log::EventOutcome::Unknown),","sourceCodeStart":1761,"sourceCodeEnd":1797,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/qq.rs#L1761-L1797","documentation":"Raised by QQChannel::listen when the loop exits with ExitReason::Reconnect — the QQ gateway explicitly asked the client to reconnect (op 7 style reconnect opcodes). Unlike InvalidSession, session_id and last_sequence are deliberately preserved so the next listen() attempts a Resume, replaying missed events per QQ's resume semantics. It is an expected, routine lifecycle signal, not a fault.","triggerScenarios":"listen() receives the server's reconnect instruction (dispatch opcode or gateway op 7) and breaks with ExitReason::Reconnect; the match arm at qq.rs:1777 bails with this message while leaving session state intact for Resume.","commonSituations":"Normal QQ gateway behavior during server-side load rebalancing or maintenance windows; happens periodically on long-lived bots and is fully recovered by one reconnect cycle.","solutions":["No code change needed — let the supervisor reconnect; Resume restores the session and event continuity","If reconnect storms occur, add or tune the reconnect backoff in the supervisor rather than suppressing this error","Watch logs for whether the subsequent Resume succeeded (session preserved) to confirm no events were missed"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(err) = channel.listen(&tx).await {\n    if format!(\"{err:#}\").contains(\"server requested reconnect\") {\n        continue; // session preserved, Resume on next listen()\n    }\n    return Err(err);\n}","preventionTips":["Do not alert on this error — server-requested reconnects are routine QQ gateway behavior","Keep session_id/last_sequence intact across reconnects so Resume can replay missed events","Tune reconnect backoff to avoid hammering the gateway during maintenance windows"],"tags":["qq","websocket","reconnect","resume","gateway","lifecycle"],"backgroundTag":"websocket-server-reconnect","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}