Skip to content

fix(discord): close old client before reconnect to prevent zombie websockets#18224

Closed
luyao618 wants to merge 1 commit into
NousResearch:mainfrom
luyao618:fix/discord-zombie-websocket-on-reconnect
Closed

fix(discord): close old client before reconnect to prevent zombie websockets#18224
luyao618 wants to merge 1 commit into
NousResearch:mainfrom
luyao618:fix/discord-zombie-websocket-on-reconnect

Conversation

@luyao618

@luyao618 luyao618 commented May 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #18187 — Discord adapter creates zombie websocket connection on reconnect, causing double responses.

Problem

When DiscordAdapter.connect() is called during a reconnect cycle (e.g. gateway restart), it unconditionally creates a new commands.Bot client without closing the previous one. The old client's websocket remains connected to Discord's gateway, so both clients fire on_message for every incoming event — resulting in double responses with different wording.

The existing MessageDeduplicator cannot prevent this because the two websockets deliver events independently, and the two on_message coroutines race on the dedup check.

Fix

Before creating a new Bot instance in connect(), check if a previous client exists and close it:

if self._client is not None:
    try:
        if not self._client.is_closed():
            await self._client.close()
    except Exception:
        logger.debug("[%s] Failed to close previous Discord client", self.name)
    finally:
        self._client = None
        self._ready_event.clear()

This ensures only one Discord websocket connection is ever active for the adapter.

Scope

  • 1 file changed: gateway/platforms/discord.py (+15 lines)
  • All 375 Discord-related tests pass

Testing

python -m pytest tests/tools/test_discord_tool.py tests/gateway/ -k discord
# 375 passed, 1 skipped

…sockets (NousResearch#18187)

When DiscordAdapter.connect() is called during reconnect, it creates a new
commands.Bot client without closing the previous one. The old client's
websocket remains connected to Discord's gateway, causing both to fire
on_message for every incoming event — resulting in double responses.

Fix: before creating a new Bot instance, check if a previous client exists
and close it. This ensures only one websocket connection is active at any
time.

Closes NousResearch#18187
@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/gateway Gateway runner, session dispatch, delivery platform/discord Discord bot adapter labels May 1, 2026
teknium1 added a commit that referenced this pull request May 2, 2026
…ect()

Covers PR #18224 fix for issue #18187 — when DiscordAdapter.connect() is
called a second time without an intervening disconnect(), the previous
commands.Bot must be closed before a new one is created. Otherwise both
websockets stay connected to Discord's gateway and both fire on_message,
producing double responses with different wording.
@teknium1

teknium1 commented May 2, 2026

Copy link
Copy Markdown
Contributor

Merged via #18758 — your commit cherry-picked onto current main with authorship preserved via rebase-merge. Added a regression test that asserts the first client ends up closed after the second connect(). Thanks!

#18758

@teknium1 teknium1 closed this May 2, 2026
nickdlkk pushed a commit to nickdlkk/hermes-agent that referenced this pull request May 11, 2026
…ect()

Covers PR NousResearch#18224 fix for issue NousResearch#18187 — when DiscordAdapter.connect() is
called a second time without an intervening disconnect(), the previous
commands.Bot must be closed before a new one is created. Otherwise both
websockets stay connected to Discord's gateway and both fire on_message,
producing double responses with different wording.
jsboige pushed a commit to jsboige/hermes-agent that referenced this pull request May 14, 2026
…ect()

Covers PR NousResearch#18224 fix for issue NousResearch#18187 — when DiscordAdapter.connect() is
called a second time without an intervening disconnect(), the previous
commands.Bot must be closed before a new one is created. Otherwise both
websockets stay connected to Discord's gateway and both fire on_message,
producing double responses with different wording.
dannyJ848 pushed a commit to dannyJ848/hermes-agent that referenced this pull request May 17, 2026
…ect()

Covers PR NousResearch#18224 fix for issue NousResearch#18187 — when DiscordAdapter.connect() is
called a second time without an intervening disconnect(), the previous
commands.Bot must be closed before a new one is created. Otherwise both
websockets stay connected to Discord's gateway and both fire on_message,
producing double responses with different wording.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…ect()

Covers PR NousResearch#18224 fix for issue NousResearch#18187 — when DiscordAdapter.connect() is
called a second time without an intervening disconnect(), the previous
commands.Bot must be closed before a new one is created. Otherwise both
websockets stay connected to Discord's gateway and both fire on_message,
producing double responses with different wording.
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…ect()

Covers PR NousResearch#18224 fix for issue NousResearch#18187 — when DiscordAdapter.connect() is
called a second time without an intervening disconnect(), the previous
commands.Bot must be closed before a new one is created. Otherwise both
websockets stay connected to Discord's gateway and both fire on_message,
producing double responses with different wording.
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 P1 High — major feature broken, no workaround platform/discord Discord bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Discord adapter creates zombie websocket connection on reconnect, causing double responses

3 participants