Skip to content

fix(whatsapp): guard bridge reconnect against hangs and unhandled rejections - #77337

Merged
kshitijk4poor merged 1 commit into
NousResearch:mainfrom
kshitijk4poor:salvage/whatsapp-reconnect-wedge-77270
Aug 3, 2026
Merged

fix(whatsapp): guard bridge reconnect against hangs and unhandled rejections#77337
kshitijk4poor merged 1 commit into
NousResearch:mainfrom
kshitijk4poor:salvage/whatsapp-reconnect-wedge-77270

Conversation

@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Summary

Guards the WhatsApp bridge reconnect path against two unrecoverable failure modes that leave the bridge permanently disconnected while its Express server keeps answering 503 to the gateway.

Root cause

startSocket() awaits fetchLatestBaileysVersion() (a plain fetch() to raw.githubusercontent.com with no AbortSignal) before creating a socket or registering event handlers. The close handler re-entered it via a bare setTimeout(startSocket, ...). On reconnect:

  1. A rejection is an unhandled promise rejection (fatal on modern Node).
  2. A stalled fetch hangs forever — nothing left to retry, bridge stays disconnected indefinitely.

Observed in the field: bridge wedged 27+ hours after a stream:error 503, logging Reconnecting in 3s... once then going silent.

Changes

  • bridge_helpers.js — two pure factory functions (keeping bridge.js side-effect-free per convention):
    • createReconnectScheduler(startFn) — catches failed startSocket() and reschedules (5s) instead of dying or going silent
    • createVersionResolver(fetchFn) — bounds version fetch with 15s timeout, falls back to last known-good version or Baileys library default
  • bridge.js — routes close-handler reconnect and gateway-mode initial connect through the scheduler; resolves WA version through the bounded resolver
  • bridge.reconnect.test.mjs — 6 regression tests: retry-after-rejection, stop-after-success, sync-throw containment, timeout fallback to default, cached-version fallback, timer cleanup

Credit

Cherry-picked from #77270 by @ATran28 (at828@proton.me). Authorship preserved via rebase-merge.

Closes #77268

…ections

startSocket() awaits useMultiFileAuthState() and fetchLatestBaileysVersion()
before it creates a socket or registers event handlers, and the close handler
re-entered it via a bare setTimeout(startSocket, ...). That leaves two
unrecoverable failure modes on a reconnect:

- a rejection is an unhandled promise rejection (fatal on modern Node)
- a hang leaves the bridge permanently disconnected with nothing left to
  retry, while its HTTP server keeps answering 503 to the gateway

The second mode was observed in the field: fetchLatestBaileysVersion() is a
plain fetch to raw.githubusercontent.com with no AbortSignal, and after a
stream:error 503 disconnect the bridge logged 'Reconnecting in 3s...' once
and then sat silent and disconnected for 27+ hours until manually restarted.

Fix, as two pure helpers in bridge_helpers.js (keeping bridge.js side-effect
free to test):

- createReconnectScheduler(): every (re)connect entry point now catches a
  failed startSocket() and reschedules it instead of dying or going silent
- createVersionResolver(): bounds the version fetch with a 15s timeout and
  falls back to the last known-good version (or the Baileys default before
  first success) instead of pending forever
@kshitijk4poor
kshitijk4poor enabled auto-merge (rebase) August 3, 2026 04:28
@kshitijk4poor
kshitijk4poor merged commit 947fdea into NousResearch:main Aug 3, 2026
33 checks passed
@kshitijk4poor
kshitijk4poor deleted the salvage/whatsapp-reconnect-wedge-77270 branch August 5, 2026 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WhatsApp bridge wedges permanently disconnected if reconnect's version fetch hangs

1 participant