Skip to content

fix(meta): use continue instead of return when processing status batches - #2715

Open
vin1i wants to merge 1 commit into
evolution-foundation:developfrom
vin1i:fix/business-status-batch-continue
Open

fix(meta): use continue instead of return when processing status batches#2715
vin1i wants to merge 1 commit into
evolution-foundation:developfrom
vin1i:fix/business-status-batch-continue

Conversation

@vin1i

@vin1i vin1i commented Aug 29, 2026

Copy link
Copy Markdown

Description

The WhatsApp Cloud API (Meta Business channel) delivers message status updates in batches: a single webhook payload can contain multiple entries in received.statuses. In BusinessStartupService.messageHandle, the loop for await (const item of received.statuses) used return in three places where per-item skipping was intended, so a single item hitting one of these paths silently aborted processing of every remaining status in the same batch (while still returning 200 to Meta):

  1. groups_ignore guard: one group (@g.us) status dropped all subsequent non-group statuses in the batch.
  2. !findMessage guard: a status for a message not present in the database (e.g. sent outside Evolution, directly via the Graph API, or from the WhatsApp Business app on the phone) dropped the rest of the batch. This is the most impactful case, since Meta commonly batches statuses for several messages into one payload. One "foreign" wamid arriving first meant delivery and read receipts went missing for messages Evolution does own, with nothing in the logs.
  3. End of the MESSAGES_DELETE branch: after correctly handling a delete event, the remaining items in the batch were never processed, so their MESSAGES_UPDATE events were not emitted, not persisted to messageUpdate, and not forwarded to Chatwoot or per-message webhooks.

This PR replaces those three return statements with continue, so each guard skips only the current item. In all three sites, return was the last statement on its code path within the iteration, so continue is behaviorally identical for the current item and only restores processing of the remaining items.

This also matches the pattern already used in the Baileys channel service (whatsapp.baileys.service.ts), whose messages.update handler uses continue for the identical per-item guards, including the same groups-ignore check.

Related Issue

Closes #2700

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)

Verification performed:

  • npm run lint:check, npm run db:generate and npm run build all pass locally (same steps as the check_code_quality CI workflow).
  • Traced the webhook flow: with a Cloud API status payload containing e.g. a group status followed by a regular status, the regular status was previously dropped (no MESSAGES_UPDATE event, no messageUpdate row, no per-message webhook call); with this change it is processed.
  • The repository has no automated test infrastructure for this service, so no unit tests were added.

Screenshots (if applicable)

N/A, control-flow-only change.

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

There is a related but distinct remaining weakness: an exception thrown inside the loop (for example the per-message axios.post(findMessage.webhookUrl, message) at the end of an iteration, or a Prisma error) propagates to the method's outer try/catch and also aborts the remaining batch. I intentionally kept this PR limited to the fix proposed in the issue to keep the diff minimal. If maintainers would like, I can submit a follow-up wrapping each iteration in a try/catch so one failing item cannot abort the batch.

WhatsApp Cloud API delivers statuses in batches; a return inside the for-await loop silently dropped all remaining items when one item hit a guard (group ignore, message not found, or after handling a delete). Replaced with continue, matching the Baileys channel pattern.

Closes evolution-foundation#2700
@sourcery-ai

sourcery-ai Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Updates Meta Cloud API status-batch control flow so group-filtered statuses, unknown messages, and completed delete events affect only the current item instead of silently preventing subsequent statuses from being processed.

Flow diagram for per-item Meta status batch processing

flowchart TD
    A[Meta status batch] --> B[Process current status]
    B --> C{groups_ignore and group status?}
    C -->|Yes| D[continue to next status]
    C -->|No| E{Message required and not found?}
    E -->|Yes| D
    E -->|No| F{MESSAGES_DELETE handled?}
    F -->|Yes| D
    F -->|No| G[Process status and emit updates]
    G --> H{More statuses?}
    D --> H
    H -->|Yes| B
    H -->|No| I[Finish batch]
Loading

File-Level Changes

Change Details Files
Preserve processing of subsequent status items in a webhook batch when the current item should be skipped or has completed delete handling.
  • Replace the groups-ignore early exit with per-item iteration control.
  • Skip unknown or externally created messages without aborting the batch.
  • Continue after processing message deletion so later update events and side effects still run.
src/api/integrations/channel/meta/whatsapp.business.service.ts

Possibly linked issues


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

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Needs a human reviewer. The change allows later items in a status batch to be processed instead of aborting the entire batch when one item is skipped. If that control flow is wrong, subsequent message records or related processing could occur and would not be removed by reverting, though the resulting data and effects are bounded and repairable.


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.

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