Skip to content

fix: wait for WA connection before returning socket - #16

Open
Gjzus11 wants to merge 1 commit into
jlucaso1:mainfrom
Gjzus11:main
Open

fix: wait for WA connection before returning socket#16
Gjzus11 wants to merge 1 commit into
jlucaso1:mainfrom
Gjzus11:main

Conversation

@Gjzus11

@Gjzus11 Gjzus11 commented May 27, 2026

Copy link
Copy Markdown

Summary

  • startWhatsAppConnection resolved immediately after makeWASocket, before the WebSocket handshake with WhatsApp completed (~700ms on average).
  • Any MCP tool call that arrived during that window received a Connection Closed error and failed silently.
  • Added a connectionReady promise that resolves on connection === 'open' (with a 20s timeout). The function now awaits this promise before returning the socket, so the MCP server only accepts requests once the socket is fully authenticated and ready.

Behaviour change

Before: send_message called immediately after server start would fail with Error: Connection Closed.
After: server startup blocks until WA confirms the session is open, then accepts tool calls.

Test plan

  • Start the MCP server cold (no prior connection open).
  • Call send_message immediately — message should succeed.
  • Confirm wa-logs.txt shows Connection opened before Message sent successfully.
  • Delete auth_info/ and restart — QR flow should still work (promise resolves on the next open after scan).

Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved WhatsApp connection reliability by ensuring the connection reaches a fully ready state before the application attempts to use it
    • Added connection timeout protection during setup (20-second limit) to prevent indefinite waiting, with proper error detection for logout scenarios while preserving automatic reconnection behavior

Review Change Stack

startWhatsAppConnection was resolving immediately after createWASocket,
before the WebSocket handshake with WhatsApp completed (~700ms). Any
tool call that arrived during that window failed with "Connection Closed".

Add a connectionReady promise that resolves on connection === "open"
(with a 20s timeout). The MCP server now only starts accepting requests
once the socket is fully authenticated and ready to send messages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

startWhatsAppConnection now blocks until the Baileys socket reaches "open" state by awaiting a connectionReady promise before returning. The function sets a 20-second timeout that rejects if the socket does not open in time, and integrates the promise resolution into existing close and open event handlers.

Changes

Connection readiness synchronization

Layer / File(s) Summary
Connection readiness promise and timeout setup
src/whatsapp.ts
A connectionReady promise and holder variables are created alongside a 20-second timeout that will reject the promise if the socket does not reach "open" state.
Readiness resolution in connection events and return
src/whatsapp.ts
Connection close and open event handlers now clear the timeout and resolve or reject the connectionReady promise; the function awaits this promise before returning the socket to ensure callers receive a ready socket.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A socket waits with promise bright,
Twenty seconds for that "open" light,
When the connection finds its way,
Ready sockets see the day!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding a wait mechanism for WhatsApp connection readiness before returning the socket, which directly matches the core purpose of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/whatsapp.ts (1)

153-155: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Non-logout close leaves the promise pending until timeout.

When connection closes for a non-logout reason, the code starts a recursive reconnection but does not clear the timeout or reject connectionReady. The original caller will wait the full 20s before receiving a timeout error, even though the socket is already closed. Additionally, the recursive call creates a new socket that is never returned to the original caller (orphaned).

Consider rejecting immediately on any close to give fast feedback:

Proposed fix
       if (statusCode !== DisconnectReason.loggedOut) {
+        clearTimeout(connectionTimeout);
+        rejectConnection?.(
+          new Error(`Connection closed: ${DisconnectReason[statusCode as number] || "Unknown"}`)
+        );
+        rejectConnection = null;
+        resolveConnection = null;
         logger.info("Reconnecting...");
         startWhatsAppConnection(logger);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/whatsapp.ts` around lines 153 - 155, The connection close handler
currently starts a new reconnection via startWhatsAppConnection when statusCode
!== DisconnectReason.loggedOut but does not reject/resolve the existing
connectionReady promise or clear its timeout, leaving the original caller
waiting and creating an orphaned socket; modify the close branch so that on any
non-logout close you immediately reject (or resolve with a failure) the existing
connectionReady promise and clear its associated timeout before triggering
startWhatsAppConnection, and ensure any socket reference created for this
attempt is cleaned up or returned to the caller to avoid orphaned sockets
(referencing connectionReady, startWhatsAppConnection, statusCode,
DisconnectReason and the timeout variable used to guard the 20s wait).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/whatsapp.ts`:
- Around line 168-170: The logout/timeout handling nulls both promise handlers
but the success path only nulls resolveConnection; update the success branch
where connectionTimeout is cleared and resolveConnection is set to null to also
set rejectConnection = null for consistency and to avoid leaving a stale
reference to the reject handler (referencing resolveConnection,
rejectConnection, and connectionTimeout).

---

Outside diff comments:
In `@src/whatsapp.ts`:
- Around line 153-155: The connection close handler currently starts a new
reconnection via startWhatsAppConnection when statusCode !==
DisconnectReason.loggedOut but does not reject/resolve the existing
connectionReady promise or clear its timeout, leaving the original caller
waiting and creating an orphaned socket; modify the close branch so that on any
non-logout close you immediately reject (or resolve with a failure) the existing
connectionReady promise and clear its associated timeout before triggering
startWhatsAppConnection, and ensure any socket reference created for this
attempt is cleaned up or returned to the caller to avoid orphaned sockets
(referencing connectionReady, startWhatsAppConnection, statusCode,
DisconnectReason and the timeout variable used to guard the 20s wait).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a92156a4-9bf3-4e40-adcf-16261fdf6fa1

📥 Commits

Reviewing files that changed from the base of the PR and between ce9b144 and 9277f2d.

📒 Files selected for processing (1)
  • src/whatsapp.ts

Comment thread src/whatsapp.ts
Comment on lines +168 to +170
clearTimeout(connectionTimeout);
resolveConnection?.();
resolveConnection = null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider nulling rejectConnection for consistency.

On logout (lines 159-160) and timeout (lines 127-128), both resolveConnection and rejectConnection are nulled. Here only resolveConnection is nulled. While functionally harmless (the promise is settled), nulling both would be consistent.

Proposed fix
        clearTimeout(connectionTimeout);
        resolveConnection?.();
        resolveConnection = null;
+       rejectConnection = null;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
clearTimeout(connectionTimeout);
resolveConnection?.();
resolveConnection = null;
clearTimeout(connectionTimeout);
resolveConnection?.();
resolveConnection = null;
rejectConnection = null;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/whatsapp.ts` around lines 168 - 170, The logout/timeout handling nulls
both promise handlers but the success path only nulls resolveConnection; update
the success branch where connectionTimeout is cleared and resolveConnection is
set to null to also set rejectConnection = null for consistency and to avoid
leaving a stale reference to the reject handler (referencing resolveConnection,
rejectConnection, and connectionTimeout).

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.

1 participant