Skip to content

fix(qqbot): prevent reconnect stall after closed websocket - #32885

Closed
qixuancao wants to merge 1 commit into
NousResearch:mainfrom
qixuancao:fix/qqbot-closed-ws-reconnect-loop
Closed

fix(qqbot): prevent reconnect stall after closed websocket#32885
qixuancao wants to merge 1 commit into
NousResearch:mainfrom
qixuancao:fix/qqbot-closed-ws-reconnect-loop

Conversation

@qixuancao

Copy link
Copy Markdown

Summary

  • make QQBot _read_events() raise when a present websocket is already closed instead of silently returning
  • clear a stale closed websocket on reconnect failure so the next loop iteration cannot reuse it
  • add regression tests covering the 4009/session-timeout reconnect stall path

Testing

  • scripts/run_tests.sh tests/gateway/test_qqbot.py -v --tb=short

Fixes #31101

Related: #17703

After a WebSocket close (e.g. code=4009 session timeout), if
_get_gateway_url() fails during reconnect, the stale self._ws was
left present-but-closed. _read_events() returned silently instead
of raising, causing _listen_loop() to reset backoff and spin forever.

- Raise RuntimeError from _read_events() when self._ws is closed.
- Clear stale closed websocket in _reconnect() on failure.
- Add regression tests verifying backoff progression is preserved.

Refs: qqbot reconnect stall bug
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/qqbot QQ Bot adapter labels May 27, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competing fix for #17703 (QQBot stops reconnecting after closed websocket). Multiple open PRs address the same root cause: #17704, #20994, #27821, #29057, #30431, #31333. This PR also clears stale ws on reconnect failure (similar to #20994's approach). Additionally references #31101 and #31771 (same symptoms, 100% CPU busy-loop).

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused QQBot investigation and regression coverage.

Automated hermes-sweeper review found this behavior already implemented on current main:

  • gateway/platforms/qqbot/adapter.py:692-697 now raises when _ws is present but already closed, preventing _read_events() from returning normally and resetting reconnect backoff.
  • gateway/platforms/qqbot/adapter.py:647-664 sends that exception through the reconnect path and increments backoff after failed reconnects.
  • tests/gateway/test_qqbot.py:2235-2256 already covers the closed-but-non-None WebSocket guard.
  • The fix landed in 3eeca4613d618618093db416b564a2b9ef8dbe6a (fix(qqbot): stop 100% CPU spin when WebSocket is closed but not None) and shipped in v2026.6.19.

The member discussion linking the competing reconnect fixes was useful; the current merged guard provides the PR's requested no-stall behavior.

@teknium1 teknium1 closed this Jul 13, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/qqbot QQ Bot adapter sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

QQ Bot adapter: _read_events() silent loop after reconnect failure prevents further retries

3 participants