Skip to content

fix(socket-mode): observe reconnect rejections#2657

Open
w3lld1 wants to merge 2 commits into
slackapi:mainfrom
w3lld1:fix/socket-mode-reconnect-rejection
Open

fix(socket-mode): observe reconnect rejections#2657
w3lld1 wants to merge 2 commits into
slackapi:mainfrom
w3lld1:fix/socket-mode-reconnect-rejection

Conversation

@w3lld1

@w3lld1 w3lld1 commented Jul 12, 2026

Copy link
Copy Markdown

Summary

  • propagate delayed reconnect callback rejections instead of leaving the returned promise pending
  • observe failures from close-triggered reconnect attempts and log them when the client is still active
  • settle a delayed reconnect cleanly when shutdown wins the race
  • add a regression test for a rejected reconnect attempt

Fixes #2656

Validation

  • npm run lint
  • npm run build
  • npm run test:unit --workspace=@slack/socket-mode (21 tests passed)

Requirements

@w3lld1 w3lld1 requested a review from a team as a code owner July 12, 2026 13:35
@changeset-bot

changeset-bot Bot commented Jul 12, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 5c8a15d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@salesforce-cla

Copy link
Copy Markdown

Thanks for the contribution! Before we can merge this, we need @w3lld1 to sign the Salesforce Inc. Contributor License Agreement.

@mwbrooks

Copy link
Copy Markdown
Member

Hi @w3lld1 👋🏻 Thanks for the pull request! 🙇🏻

❓ Can you please sign our CLA - once signed, we can begin reviewing your pull request and enabling the workflow checks.

@mwbrooks mwbrooks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clean, focused fix - it's focused on #2656 and the code changes track it closely. I've left comments on two things that we'll need addressed along with the signed CLA. Thanks!

this.delayReconnectAttempt(this.start);
void this.delayReconnectAttempt(this.start).catch((error) => {
if (!this.shuttingDown) {
this.logger.error(`Failed to reconnect Socket Mode client: ${error}`);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: Nice - the if (!this.shuttingDown) guard here is great. It surfaces the real reconnect failure while keeping the log quiet during a normal disconnect() race, which is the whole point of the fix. Thanks for the care.

return new Promise((resolve, reject) => {
setTimeout(() => {
if (this.shuttingDown) {
this.logger.debug('Client shutting down, will not attempt reconnect.');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: We should handle this differently. Resolving with undefined as T works for the close-handler, but retrieveWSSURL also calls delayReconnectAttempt (line 276) and uses the result as a WebSocket URL.

If disconnect() races a retry inside retrieveWSSURL, this now returns undefined up through the recursion and start() ends up constructing new SlackWebSocket({ url: undefined, ... }). Not ideal.

A couple of options come to mind:

  1. Short-circuit earlier so we never call into start() / return a URL when we know we're shutting down. This may match the approach throughout the package.
  2. Reject with a specific "shutdown in progress" error and have callers (both the close handler and retrieveWSSURL) swallow it explicitly. That keeps the type honest and avoids the undefined-as-URL path.

});

describe('reconnect', () => {
it('should observe a rejected reconnect attempt', async () => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: Really appreciate having a regression test alongside the fix - it locks in the main failure mode from #2656.

client.emit('close');
await sleep(10);

sinon.assert.calledWith(errorLog, 'Failed to reconnect Socket Mode client: Error: reconnect failed');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: We should add a second test case here that covers the !this.shuttingDown guard.

@mwbrooks mwbrooks added bug M-T: A confirmed bug report. Issues are confirmed when the reproduction steps are documented semver:patch pkg:socket-mode applies to `@slack/socket-mode` labels Jul 13, 2026
@mwbrooks mwbrooks added this to the socket-mode@next milestone Jul 13, 2026
Signed-off-by: w3lld1 <42353747+w3lld1@users.noreply.github.com>
@w3lld1

w3lld1 commented Jul 13, 2026

Copy link
Copy Markdown
Author

Addressed both review points in 5c8a15dc: the delayed reconnect now rejects with a typed shutdown signal instead of resolving undefined, the close handler suppresses only that expected signal, and a regression test covers the disconnect-during-delay guard.

Validation: the socket-mode unit suite passes (22 tests), the full repository Biome check passes, and git diff --check passes. The Salesforce CLA check is now green.

@w3lld1

w3lld1 commented Jul 14, 2026

Copy link
Copy Markdown
Author

Thanks for the review. The follow-up commit 5c8a15dc addresses both requested changes:

  • delayReconnectAttempt() now rejects with a dedicated SocketModeClientShuttingDownError instead of returning undefined, and the close handler suppresses only that expected shutdown error;
  • the second regression test covers the shutdown race and verifies that start() is not called and no reconnect error is logged.

Fresh validation:

  • npm run build
  • npm run lint
  • npm run test:unit --workspace=@slack/socket-mode — 22 passed
  • git diff --check

The remaining CLA signature requires the account holder to complete the Salesforce CLA form manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug M-T: A confirmed bug report. Issues are confirmed when the reproduction steps are documented cla:signed pkg:socket-mode applies to `@slack/socket-mode` semver:patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SocketModeClient reconnect rejection is unhandled when disconnect races retry

2 participants