Skip to content

Conversation

@FelipeFrancca
Copy link

@FelipeFrancca FelipeFrancca commented Jan 16, 2026

📋 Description

This PR fixes the infinite reconnection loop that prevents QR code generation in Evolution API versions v2.1.0, v2.1.1, and v2.2.0.

Problem:
When attempting to generate a QR code for WhatsApp connection, the Baileys integration enters an infinite reconnection loop. The connectionUpdate event handler triggers reconnection immediately when the connection closes (which is normal during initial QR code generation), preventing the QR code from ever being generated and displayed.

Root Cause:
The issue occurs in whatsapp.baileys.service.ts where the connection close event triggers shouldReconnect logic before the initial QR code is generated. Since statusCode is undefined during the first connection attempt, the code incorrectly attempts to reconnect, creating an endless loop.

Solution:
Added an isInitialConnection check that prevents reconnection attempts when:

  • The instance is not yet authenticated (!this.instance.wuid)
  • AND no QR code has been generated yet (this.instance.qrcode.count === 0)

This allows the first connection to close gracefully so the QR code can be generated and sent to the client.

Changes:

  • Modified connectionUpdate method in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts (lines 421-440)
  • Added conditional check before reconnection logic
  • Preserved all existing functionality for authenticated connections

🔗 Related Issue

Closes #2341

🧪 Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🔧 Refactoring (no functional changes)
  • ⚡ Performance improvement
  • 🧹 Code cleanup
  • 🔒 Security fix

🧪 Testing

  • Manual testing completed
  • Functionality verified in development environment
  • No breaking changes introduced
  • Tested with different connection types (if applicable)

Test Results:

  • ✅ QR code generation: Working perfectly (count: 9, base64 data received)
  • ✅ WhatsApp connection: Successfully established after scanning QR code
  • ✅ Chatwoot integration: Verified working with connected WhatsApp instance
  • ✅ Reconnection logic: Still works correctly for authenticated instances
  • ✅ Multiple instances: Tested creating and connecting multiple WhatsApp instances

Testing Environment:

  • Evolution API v2.3.7 (forked with fix)
  • Node.js v22.13.1
  • PostgreSQL 17.5
  • Redis Alpine
  • Chatwoot integration enabled
  • Docker environment (Alpine Linux 3.20.3)

📸 Screenshots (if applicable)

Before Fix:

  • QR code count always stuck at 0
  • Infinite reconnection loop in logs
  • No QR code ever displayed

After Fix:

  • QR code successfully generated (count: 9)
  • QR code displayed in ASCII art in terminal
  • Base64 QR code available via API endpoint
  • WhatsApp connection established successfully

✅ Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have manually tested my changes thoroughly
  • I have verified the changes work with different scenarios
  • Any dependent changes have been merged and published

📝 Additional Notes

Impact: This is a critical bug fix that restores QR code generation functionality for new WhatsApp connections. Without this fix, users cannot establish new WhatsApp connections in affected versions.

Backward Compatibility: This fix is fully backward compatible. It only affects the initial connection flow and does not change behavior for already authenticated instances.

Code Changes Summary:

// Added check before reconnection logic (lines 421-427)
const isInitialConnection = !this.instance.wuid && this.instance.qrcode.count === 0;

if (isInitialConnection) {
  this.logger.info('Initial connection closed, waiting for QR code generation...');
  return; // Prevents infinite reconnection loop
}

// Existing reconnection logic continues for authenticated instances
if (shouldReconnect) {
  // ... existing code
}

Versions Affected: v2.1.0, v2.1.1, v2.2.0
Fix Verified In: v2.3.7

Summary by Sourcery

Prevent infinite reconnection loops during initial WhatsApp QR code setup by adjusting Baileys connection handling.

Bug Fixes:

  • Avoid triggering reconnection on the initial unauthenticated connection close so QR codes can be generated and delivered correctly.

Enhancements:

  • Add clearer logging for initial connection handling and reconnect attempts in the Baileys WhatsApp service.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 16, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts Baileys WhatsApp connection handling to avoid reconnecting during the very first, unauthenticated connection so QR codes can be generated, while preserving existing reconnection behavior for authenticated/normal sessions.

Sequence diagram for updated Baileys connection close handling

sequenceDiagram
  participant BaileysSocket as BaileysSocket
  participant BaileysStartupService as BaileysStartupService
  participant WhatsappAPI as WhatsappAPI

  BaileysSocket->>BaileysStartupService: connectionUpdate(connection close, lastDisconnect)
  activate BaileysStartupService
  BaileysStartupService->>BaileysStartupService: read lastDisconnect.error.statusCode
  BaileysStartupService->>BaileysStartupService: compute isInitialConnection = !instance.wuid && instance.qrcode.count == 0

  alt initial_unauthenticated_connection
    BaileysStartupService->>BaileysStartupService: logger.info(Initial connection closed, waiting for QR code generation...)
    BaileysStartupService-->>BaileysSocket: return (no reconnect)
  else authenticated_or_qr_generated
    BaileysStartupService->>BaileysStartupService: compute shouldReconnect based on statusCode
    alt shouldReconnect
      BaileysStartupService->>BaileysStartupService: logger.warn(Connection lost, reconnecting...)
      BaileysStartupService->>WhatsappAPI: connectToWhatsapp(phoneNumber)
      WhatsappAPI-->>BaileysStartupService: connection established or closed
    else shouldNotReconnect
      BaileysStartupService->>BaileysStartupService: sendDataWebhook(STATUS_INSTANCE, disconnected)
    end
  end
  deactivate BaileysStartupService
Loading

File-Level Changes

Change Details Files
Prevent reconnection during the initial unauthenticated connection close so QR code generation can complete, and enhance logging around connection loss and reconnection.
  • Introduce an isInitialConnection flag based on missing wuid and zero QR code count to detect the first-connection QR-generation phase.
  • Short‑circuit the connectionUpdate handler on close events during the initial connection by logging and returning early instead of running reconnection logic.
  • Keep the existing shouldReconnect status-code based logic for subsequent/normal connections.
  • Add a warning log message when reconnection is triggered, including the status code for easier diagnosis of future connection issues.
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Assessment against linked issues

Issue Objective Addressed Explanation
#2341 Fix the bug that prevents WhatsApp (including WhatsApp Business) from connecting in Evolution by allowing the initial QR-code-based connection flow to complete successfully.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The isInitialConnection check assumes this.instance.qrcode is always defined; consider using optional chaining or a default (this.instance.qrcode?.count ?? 0) to avoid potential runtime errors if qrcode is undefined on some paths.
  • The new inline comments are in Portuguese while surrounding code and logs are in English; consider standardizing the comment language to match the rest of the file for consistency.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `isInitialConnection` check assumes `this.instance.qrcode` is always defined; consider using optional chaining or a default (`this.instance.qrcode?.count ?? 0`) to avoid potential runtime errors if `qrcode` is undefined on some paths.
- The new inline comments are in Portuguese while surrounding code and logs are in English; consider standardizing the comment language to match the rest of the file for consistency.

## Individual Comments

### Comment 1
<location> `src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts:441` </location>
<code_context>
+      
       const shouldReconnect = !codesToNotReconnect.includes(statusCode);
       if (shouldReconnect) {
+        this.logger.warn(`Connection lost (status: ${statusCode}), reconnecting...`);
         await this.connectToWhatsapp(this.phoneNumber);
       } else {
</code_context>

<issue_to_address>
**suggestion:** Consider symmetric logging when opting not to reconnect

When `shouldReconnect` is false there’s no corresponding log explaining that reconnection is being skipped and why. Please add a log in the `else` branch (e.g. info/warn) that includes the `statusCode` and mentions that reconnect is skipped because it’s in `codesToNotReconnect`, to improve debugging and correlation with webhook events.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


const shouldReconnect = !codesToNotReconnect.includes(statusCode);
if (shouldReconnect) {
this.logger.warn(`Connection lost (status: ${statusCode}), reconnecting...`);
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Consider symmetric logging when opting not to reconnect

When shouldReconnect is false there’s no corresponding log explaining that reconnection is being skipped and why. Please add a log in the else branch (e.g. info/warn) that includes the statusCode and mentions that reconnect is skipped because it’s in codesToNotReconnect, to improve debugging and correlation with webhook events.

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 Business não conecta na Evolution

1 participant