zeroclaw-labs/zeroclaw · warning
QQ WebSocket connection closed: server requested reconnect (
Error message
QQ WebSocket connection closed: server requested reconnect (resume will be attempted)
What it means
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.
Source
Thrown at crates/zeroclaw-channels/src/qq.rs:1779
}
}
}
// Persist sequence number for potential resume on next reconnect
*self.last_sequence.write().await = if sequence >= 0 { Some(sequence) } else { None };
match exit_reason {
ExitReason::InvalidSession => {
// Clear stored session so next reconnect does a fresh Identify
*self.session_id.write().await = None;
*self.last_sequence.write().await = None;
anyhow::bail!(
"QQ WebSocket connection closed: invalid session (fresh auth required)"
)
}
ExitReason::Reconnect => {
// Session state preserved — supervisor will reconnect and we'll attempt Resume
anyhow::bail!(
"QQ WebSocket connection closed: server requested reconnect (resume will be attempted)"
)
}
ExitReason::Close(ref frame) => {
let (code, reason) = frame
.as_ref()
.map(|f| (f.code.to_string(), f.reason.to_string()))
.unwrap_or_else(|| ("unknown".into(), "none".into()));
::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");
anyhow::bail!(
"QQ WebSocket connection closed: close_code={code}, reason=\"{reason}\""
)
}
ExitReason::StreamEnded => {
::zeroclaw_log::record!(
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
.with_outcome(::zeroclaw_log::EventOutcome::Unknown),View on GitHub (pinned to 88bb9c8533)
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
Defensive patterns
Strategy: retry
Try / catch
if let Err(err) = channel.listen(&tx).await {
if format!("{err:#}").contains("server requested reconnect") {
continue; // session preserved, Resume on next listen()
}
return Err(err);
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- QQ WebSocket connection closed: invalid session (fresh auth
- QQ WebSocket connection closed: close_code={code}, reason="{
- QQ WebSocket connection closed: stream ended unexpectedly
- WebSocket stream ended
- QQ gateway request failed ({status}): {err}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/af0054678ff85b20.
Report an issue: GitHub.