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

  1. No code change needed — let the supervisor reconnect; Resume restores the session and event continuity
  2. If reconnect storms occur, add or tune the reconnect backoff in the supervisor rather than suppressing this error
  3. 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

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

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/af0054678ff85b20. Report an issue: GitHub.