Skip to content

fix(slack): close previous handler in connect() to prevent zombie Socket Mode connections#18982

Closed
nftpoetrist wants to merge 1 commit into
NousResearch:mainfrom
nftpoetrist:fix/18980-slack-zombie-socket-handler
Closed

fix(slack): close previous handler in connect() to prevent zombie Socket Mode connections#18982
nftpoetrist wants to merge 1 commit into
NousResearch:mainfrom
nftpoetrist:fix/18980-slack-zombie-socket-handler

Conversation

@nftpoetrist

Copy link
Copy Markdown
Contributor

What does this PR do?

SlackAdapter.connect() overwrote self._handler, self._app, and self._socket_mode_task without closing the prior AsyncSocketModeHandler first. If connect() was called a second time on the same adapter (e.g. during a gateway restart or in-process reconnect attempt), the old Socket Mode websocket stayed alive. Both the old and new connections received every Slack event and dispatched it twice — producing double responses with different wording.

This is the same bug that affected DiscordAdapter (#18187, fixed in #18758 merged today). Parity fix: adds the same close-before-reassign guard that DiscordAdapter.connect() already has.

One-line guard in connect()if self._handler is not None: await self._handler.close_async() followed by finally: self._handler = None; self._app = None. When _handler is None (fresh adapter, first connect()) the block is a harmless no-op. Scoped to the handler/app fields only — no behavior change for any path that does not call connect() twice.

Related Issue

Fixes #18980

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests
  • ♻️ Refactor
  • 🎯 New skill

Changes Made

  • gateway/platforms/slack.py: add close-before-reassign guard in connect() before self._app = AsyncApp(...) (+10 lines)
  • tests/gateway/test_slack.py: add test_reconnect_closes_previous_handler_to_prevent_zombie_socket to TestSlackConnectCleanup (+54 lines)

How to Test

python3.11 -m pytest tests/gateway/test_slack.py::TestSlackConnectCleanup -v --override-ini="addopts="

Checklist

Code

  • Contributing Guide read
  • Conventional Commits
  • No duplicate PR
  • Single logical change only
  • pytest passing
  • Tests added
  • Platform: macOS

Documentation & Housekeeping

  • Docs updated — N/A
  • cli-config.yaml.example — N/A
  • CONTRIBUTING.md/AGENTS.md — N/A
  • Cross-platform impact — N/A
  • Tool descriptions — N/A

…ket Mode connections

SlackAdapter.connect() overwrote self._handler, self._app, and
self._socket_mode_task without closing the prior AsyncSocketModeHandler
first. If connect() was called a second time on the same adapter (e.g.
during a gateway restart or in-process reconnect attempt), the old Socket
Mode websocket stayed alive. Both the old and new connections received
every Slack event and dispatched it twice — producing double responses
with different wording, the same bug that affected DiscordAdapter (NousResearch#18187,
fixed in NousResearch#18758).

Fix: add a close-before-reassign guard at the start of the connection
setup path, mirroring the guard DiscordAdapter.connect() already has.
When self._handler is None (fresh adapter, first connect()) the block is
a harmless no-op. Scoped to the handler/app fields only — no behavior
change for any path that does not call connect() twice.

Fixes NousResearch#18980
@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/slack Slack app adapter labels May 2, 2026
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Merged via PR #19181. Your commit was cherry-picked onto current main with authorship preserved. Clean parity fix with the Discord equivalent — thanks @nftpoetrist!

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/slack Slack app adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(slack): close previous handler/task in connect() to prevent zombie Socket Mode connections

3 participants