Skip to content

fix(whatsmeow): apply store.SetWAVersion to update WhatsApp client ha… - #229

Open
dbadaniel wants to merge 1 commit into
evolution-foundation:developfrom
dbadaniel:fix/upstream-client-version-405
Open

dbadaniel wants to merge 1 commit into
evolution-foundation:developfrom
dbadaniel:fix/upstream-client-version-405

Conversation

@dbadaniel

@dbadaniel dbadaniel commented Nov 3, 2026 •

Copy link
Copy Markdown

Description

Fixes recurrent WhatsApp connection drops and handshake failures caused by Client outdated (405) connect failure (client version: 2.3000.1042386815).

Root Cause

Although fetchWhatsAppWebVersion() successfully fetches the active WhatsApp Web revision from https://web.whatsapp.com/sw.js (e.g., 2.3000.1052712929), the code was previously only setting store.DeviceProps.Version.

In whatsmeow, the actual WebSocket connection handshake payload uses store.BaseClientPayload.UserAgent.AppVersion, which is only updated when store.SetWAVersion(...) is called. Because store.SetWAVersion was never invoked, whatsmeow always presented its static library default version (2.3000.1042386815) during the handshake. When WhatsApp servers deprecate that specific revision, they reject the WebSocket handshake with HTTP 405 Outdated, causing reconnection loops and EOF drops.

Changes

  1. Added store.SetWAVersion(store.WAVersionContainer{...}) in StartClient so the resolved web version or configured version actually updates BaseClientPayload.UserAgent.AppVersion.
  2. Added a modern fallback version (2.3000.1052812464) in case the dynamic web fetch fails, preventing the client from falling back to the deprecated 1042386815.
  3. Added a browser User-Agent and a 10s timeout to fetchWhatsAppWebVersion() to avoid hanging or Cloudflare edge blocks.
  4. Added unit test version_test.go verifying that store.SetWAVersion updates store.BaseClientPayload.UserAgent.AppVersion.

Related Issue

Fixes 405 Client Outdated connect failures on WhatsApp Web handshake.

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

Testing

  • Manual testing completed
  • Functionality verified in development environment
  • No breaking changes introduced

Tested with unit test TestSetWAVersionUpdatesBaseClientPayload and verified that BaseClientPayload.UserAgent.AppVersion is successfully updated to match the active WhatsApp Web client revision.

Screenshots (if applicable)

N/A

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have tested my changes thoroughly
  • Any dependent changes have been merged and published

Additional Notes

None.

Summary by Sourcery

Update the WhatsApp client version handling to keep handshake metadata current and prevent recurring connection drops caused by deprecated client revisions.

Bug Fixes:

  • Ensure the WhatsApp client handshake uses the active configured or fetched Web version to prevent outdated-client 405 connection failures.
  • Add a modern fallback WhatsApp version when configuration or version discovery is unavailable.
  • Make WhatsApp Web version discovery more reliable with a browser User-Agent and request timeout.

Tests:

  • Add coverage confirming that setting the WhatsApp version updates the handshake payload version.

@sourcery-ai

sourcery-ai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The PR fixes outdated WhatsApp Web handshakes by applying the resolved client version through store.SetWAVersion, adds a modern fallback and more robust version fetching, and tests that the handshake payload receives the selected version.

Sequence diagram for WhatsApp client version selection and handshake

sequenceDiagram
    participant StartClient
    participant WhatsAppWeb
    participant Store
    participant WhatsAppServer

    StartClient->>StartClient: fetchWhatsAppWebVersion()
    alt configured version
        StartClient->>Store: SetWAVersion(configured version)
    else fetched version
        StartClient->>WhatsAppWeb: GET /sw.js with User-Agent
        WhatsAppWeb-->>StartClient: active web version
        StartClient->>Store: SetWAVersion(web version)
    else fetch fails or version is incomplete
        StartClient->>Store: SetWAVersion(2.3000.1052812464)
    end
    Store-->>Store: BaseClientPayload.UserAgent.AppVersion updated
    StartClient->>WhatsAppServer: WebSocket handshake
    WhatsAppServer-->>StartClient: handshake accepted with current client version
Loading

Flow diagram for WhatsApp Web version resolution

flowchart TD
    A[StartClient] --> B{Configured version available?}
    B -- Yes --> E[Select configured version]
    B -- No --> C["fetchWhatsAppWebVersion()"]
    C --> D{Fetch succeeds?}
    D -- Yes --> F[Select web version]
    D -- No --> G[Select fallback 2.3000.1052812464]
    E --> H[Set DeviceProps.Version]
    F --> H
    G --> H
    H --> I[store.SetWAVersion]
    I --> J[Update BaseClientPayload.UserAgent.AppVersion]
    J --> K[WebSocket handshake]
Loading

File-Level Changes

Change Details Files
Synchronize the WhatsApp version used in device properties and the WhatsApp Web handshake payload.
  • Apply configured or dynamically fetched versions through store.SetWAVersion.
  • Continue updating store.DeviceProps.Version with the resolved version.
  • Use a modern hard-coded version when configuration or web-version discovery produces an incomplete version.
  • Add logging for the selected source and final payload version.
pkg/whatsmeow/service/whatsmeow.go
Make WhatsApp Web version discovery more resilient to network and edge-service behavior.
  • Replace the default HTTP GET with a request carrying a browser User-Agent.
  • Enforce a 10-second request timeout while fetching sw.js.
pkg/whatsmeow/service/whatsmeow.go
Add coverage for propagation of the WhatsApp version into the handshake payload.
  • Verify SetWAVersion updates the stored version.
  • Verify BaseClientPayload.UserAgent.AppVersion contains the expected major, minor, and patch values.
pkg/whatsmeow/service/version_test.go

Possibly linked issues

  • #fix(whatsmeow): call store.SetWAVersion with dynamic webVersion to prevent 405 Client Outdated: The PR calls store.SetWAVersion with the resolved web/config version, directly addressing the issue’s outdated handshake version and 405 failures.
  • #unknown: Both target the same 405 outdated-version connection failure; the PR updates the handshake version dynamically rather than updating the submodule pin.

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

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

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="pkg/whatsmeow/service/version_test.go" line_range="11" />
<code_context>
+
+func TestSetWAVersionUpdatesBaseClientPayload(t *testing.T) {
+	testVersion := store.WAVersionContainer{2, 3000, 1052812464}
+	store.SetWAVersion(testVersion)
+
+	gotVersion := store.GetWAVersion()
</code_context>
<issue_to_address>
**Handshake integration goes untested**

When startClient omits its SetWAVersion call or passes a version other than the one resolved for the client, `TestSetWAVersionUpdatesBaseClientPayload` calls `store.SetWAVersion(testVersion)` at line 11 itself, so it still passes if `StartClient` omits the changed call or supplies the wrong resolved version; the handshake can remain outdated.

Exercise the StartClient version-setting path with a controlled resolved version and assert the resulting handshake payload.
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: pkg/whatsmeow/service/version_test.go:11


Sourcery is free for open source - if you like our reviews please consider sharing them ✨


func TestSetWAVersionUpdatesBaseClientPayload(t *testing.T) {
testVersion := store.WAVersionContainer{2, 3000, 1052812464}
store.SetWAVersion(testVersion)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium · Handshake integration goes untested

When startClient omits its SetWAVersion call or passes a version other than the one resolved for the client, TestSetWAVersionUpdatesBaseClientPayload calls store.SetWAVersion(testVersion) at line 11 itself, so it still passes if StartClient omits the changed call or supplies the wrong resolved version; the handshake can remain outdated.

Exercise the StartClient version-setting path with a controlled resolved version and assert the resulting handshake payload.

Prompt for AI agents
In `pkg/whatsmeow/service/version_test.go` at line 11:

**Handshake integration goes untested**

When startClient omits its SetWAVersion call or passes a version other than the one resolved for the client, `TestSetWAVersionUpdatesBaseClientPayload` calls `store.SetWAVersion(testVersion)` at line 11 itself, so it still passes if `StartClient` omits the changed call or supplies the wrong resolved version; the handshake can remain outdated.

Exercise the StartClient version-setting path with a controlled resolved version and assert the resulting handshake payload.

joaopaulobrasilio added a commit to joaopaulobrasilio/evolution-go that referenced this pull request Nov 3, 2026
…outdated 405)

Desde 02/11/2026 o WhatsApp recusa a versao 2.3000.1042386815, fixa no
whatsmeow, com "Client outdated (405)": nenhuma instancia conecta nem pareia,
e o /instance/pair falha com "websocket disconnected before info query
returned response".

O StartClient ja buscava a versao atual em web.whatsapp.com/sw.js (ou lia
WHATSAPP_VERSION_*), mas so gravava em store.DeviceProps.Version, que vai no
cadastro do aparelho. A versao do handshake e a de store.SetWAVersion, que
nunca era chamada.

- resolveWAVersion escolhe: configurada > WhatsApp Web > reserva
  (2.3000.1052682108, lida em 02/11), so se mais nova que a do whatsmeow.
- applyWAVersion chama store.SetWAVersion e grava o DeviceProps, sob mutex
  porque a versao e global e varias instancias sobem juntas.
- A busca da versao ganha timeout de 10 s; sem ele, um WhatsApp Web lento
  travava o StartClient.

Mesma correcao dos PRs evolution-foundation#227 e evolution-foundation#229 do upstream, ainda abertos. Testado em
producao na imagem hub.cliiz.net/evogo:1.1.1-pg.
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