zeroclaw-labs/zeroclaw · error

QQ WebSocket connection closed: invalid session (fresh auth

Error message

QQ WebSocket connection closed: invalid session (fresh auth required)

What it means

Raised by QQChannel::listen when its WebSocket gateway loop exits with ExitReason::InvalidSession — the server declared the session invalid (op 9 after Identify, or a rejected Resume). Before bailing, the handler clears session_id and last_sequence so the next listen() call performs a fresh Identify instead of a doomed Resume. This is a recoverable by-design error: the supervisor reconnects and re-authenticates from scratch, but events during the gap are not replayed.

Source

Thrown at crates/zeroclaw-channels/src/qq.rs:1773

                                exit_reason = ExitReason::ChannelClosed;
                                break 'outer;
                            }
                        }
                        _ => {}
                    }
                }
            }
        }

        // 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}\""
                )

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Rely on the supervisor's reconnect loop — the next listen() automatically does a fresh Identify and recovers
  2. If it recurs in a tight loop, verify the bot credentials (AppID/secret) and system clock, since a fresh Identify that also fails points to auth problems
  3. Make sure only one process consumes a given QQ bot's WebSocket connection
Defensive patterns

Strategy: retry

Try / catch

loop {
    if let Err(err) = channel.listen(&tx).await {
        if format!("{err:#}").contains("invalid session") {
            // session state already cleared; next listen() does fresh Identify
            tokio::time::sleep(backoff.next()).await;
            continue;
        }
        return Err(err);
    }
}

Prevention

When it happens

Trigger: listen() attempts Resume with a session_id that the QQ gateway no longer recognizes (disconnect longer than the resume window), or receives an invalid-session reply right after Identify. The match arm at qq.rs:1769 clears session state and bails.

Common situations: Bot resumed after suspend, deploy, or a long network partition with a stale session id; QQ invalidating sessions during platform maintenance; two instances running with the same QQ bot credentials, each invalidating the other's session.

Understand the failure class

Related errors


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