You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After a prolonged network outage, QQ stops receiving messages permanently until the OpenClaw gateway is restarted. The channel still reports running: true, connected: true, and lastError: null after the SDK has exhausted all reconnect attempts.
This is a separately reproduced failure path related to #301: the socket does close and retries do run, but recovery stops after the retry budget is exhausted. Heartbeat / half-open socket detection from #301 is a separate trigger.
Environment
OpenClaw: 2026.9.2
Plugin: @tencent-connect/openclaw-qqbot@2.0.3
SDK: @tencent-connect/qqbot-nodejs@1.0.4
macOS, Apple Silicon; managed gateway configured to use Node.js 24.18.0
Transport: WebSocket
Relevant plugin and SDK source also matches current main at a4479eea5931afdd3d504ac3b1c0860025c4d171 and ca55d9c395b582b7fcfad0ec27209c35dd04e0b3, respectively.
Observed incident
Sanitized local logs from September 7, 2026 (UTC+08:00):
11:13:39 Gateway ready
11:34:40 WebSocket closed: 1006
11:34:41 Connection failed: Network error [/gateway]: fetch failed
Client network socket disconnected before secure TLS connection was established
... exactly 100 failed connection attempts ...
13:15:36 Max reconnect attempts reached or aborted
Most attempts failed while fetching /gateway; the final attempts failed fetching an access token. After network recovery, sending a message from QQ produced no reply. No further reconnect attempts followed the exhaustion log. A read-only channel status query in that state returned:
The displayed last-connected timestamp was still the 11:13 connection. Restarting the gateway is the operator's existing workaround; no restart or live configuration change was performed during this diagnosis.
Reproduction
Start the bot and wait for READY.
Lose the socket, then make token/gateway discovery fail long enough to exhaust 100 reconnect attempts.
Restore connectivity.
Observe that the SDK no longer reconnects, the plugin start task remains pending, and OpenClaw still reports the channel connected.
An isolated Node.js reproduction against the installed SDK used a local WebSocket server: READY → server socket termination → 100 injected gateway-discovery failures → discovery restored. Only reconnect delays were compressed; the SDK's connection and retry code was unchanged. Result:
SDK GatewayConnection.scheduleReconnect() only logs and returns after exhaustion. start() remains pending until an abort signal, so the host cannot observe the terminal transport failure.
SDK gateway discovery failures only log and schedule another retry; they do not call onError. Socket close also has no disconnection callback to the plugin.
Plugin src/gateway/lifecycle.ts sets connected: true on READY/RESUMED, but never clears it on disconnection. Its onError handler only patches lastError.
OpenClaw's health monitor trusts the supplied connection state. Without a transport-activity timestamp, it cannot distinguish this stale state from an intentionally quiet connected channel.
Expected behavior / repair boundary
The SDK should report disconnection, report connection failures, and settle its startup lifecycle when recovery is exhausted. The plugin should forward those events into channel status, clear stale errors after READY/RESUMED, and clean up the failed instance so the host can restart the account. Merely increasing the retry limit postpones the same failure.
The initial TLS outage and real post-fix QQ delivery are separate proof boundaries; this report confirms the recovery dead end rather than claiming to diagnose the original network failure.
Proposed fixes and validation
SDK lifecycle repair: fix(gateway): settle exhausted recovery and report disconnects qqbot-nodejs#6 — report disconnects, reject terminal/exhausted recovery, clean up cancelled or failed connection lifetimes. All 12 new regressions fail on the SDK base and pass with the patch; full suite 178/178 passes with the available toolchain. Existing clean-install / coverage blockers are documented in that PR.
Plugin integration: fix(gateway): recover QQ channel state after disconnects #314 — synchronize channel status, preserve the disconnect timestamp, clear stale errors on recovery, and release failed account resources. All 5 new regressions fail on the plugin base and pass with the SDK candidate, including a local WebSocket test that receives a new inbound message after the host restarts the exhausted account.
The plugin PR is deliberately draft until the SDK fix is published and its dependency floor / lockfile can be updated to the real released version. The current SDK 1.0.4 cannot run the new event listener. Real QQ-platform post-fix delivery remains unverified; the operator's running gateway has not been changed.
Summary
After a prolonged network outage, QQ stops receiving messages permanently until the OpenClaw gateway is restarted. The channel still reports
running: true,connected: true, andlastError: nullafter the SDK has exhausted all reconnect attempts.This is a separately reproduced failure path related to #301: the socket does close and retries do run, but recovery stops after the retry budget is exhausted. Heartbeat / half-open socket detection from #301 is a separate trigger.
Environment
@tencent-connect/openclaw-qqbot@2.0.3@tencent-connect/qqbot-nodejs@1.0.4a4479eea5931afdd3d504ac3b1c0860025c4d171andca55d9c395b582b7fcfad0ec27209c35dd04e0b3, respectively.Observed incident
Sanitized local logs from September 7, 2026 (UTC+08:00):
Most attempts failed while fetching
/gateway; the final attempts failed fetching an access token. After network recovery, sending a message from QQ produced no reply. No further reconnect attempts followed the exhaustion log. A read-only channel status query in that state returned:{ "configured": true, "running": true, "connected": true, "lastError": null }The displayed last-connected timestamp was still the 11:13 connection. Restarting the gateway is the operator's existing workaround; no restart or live configuration change was performed during this diagnosis.
Reproduction
An isolated Node.js reproduction against the installed SDK used a local WebSocket server: READY → server socket termination → 100 injected gateway-discovery failures → discovery restored. Only reconnect delays were compressed; the SDK's connection and retry code was unchanged. Result:
{ "ready": 1, "connections": 1, "failedAttempts": 100, "retryExhausted": true, "reconnectedAfterRecovery": false, "startPromiseSettled": false, "errorCallbacks": 0 }Root cause
GatewayConnection.scheduleReconnect()only logs and returns after exhaustion.start()remains pending until an abort signal, so the host cannot observe the terminal transport failure.onError. Socket close also has no disconnection callback to the plugin.src/gateway/lifecycle.tssetsconnected: trueon READY/RESUMED, but never clears it on disconnection. ItsonErrorhandler only patcheslastError.Expected behavior / repair boundary
The SDK should report disconnection, report connection failures, and settle its startup lifecycle when recovery is exhausted. The plugin should forward those events into channel status, clear stale errors after READY/RESUMED, and clean up the failed instance so the host can restart the account. Merely increasing the retry limit postpones the same failure.
The initial TLS outage and real post-fix QQ delivery are separate proof boundaries; this report confirms the recovery dead end rather than claiming to diagnose the original network failure.
Proposed fixes and validation
The plugin PR is deliberately draft until the SDK fix is published and its dependency floor / lockfile can be updated to the real released version. The current SDK 1.0.4 cannot run the new event listener. Real QQ-platform post-fix delivery remains unverified; the operator's running gateway has not been changed.