Skip to content

fix: restore MsgKey._serialized on newer WA Web builds - #201901

Open
netobasilio wants to merge 2 commits into
wwebjs:mainfrom
netobasilio:fix/sendmessage-msgkey-serialized-fallback
Open

netobasilio wants to merge 2 commits into
wwebjs:mainfrom
netobasilio:fix/sendmessage-msgkey-serialized-fallback

Conversation

@netobasilio

@netobasilio netobasilio commented Sep 1, 2026 •

Copy link
Copy Markdown

Description

On WA Web 2.3000.1043xxx+ a MsgKey no longer exposes _serialized. The value is
still there, reachable through the minified $1 property and through toString(),
but the named property is gone.

Every page-side read of key._serialized then returns undefined. The most visible one
is the end of WWebJS.sendMessage:

return window.require('WAWebCollections').Msg.get(newMsgKey._serialized);

This becomes Msg.get(undefined), so Client.sendMessage resolves to undefined
even though the message was actually delivered. Callers that check the return value
report a successful send as a failure, and there is no message id to track acks with.
The same pattern breaks editMessage (Msg.get(msg.id._serialized)) and the
lastMessage lookup in getChatModel (chat.lastReceivedKey._serialized).

This PR adds a _serialized getter to WAWebMsgKey.prototype when LoadUtils runs.
The getter returns toString(), so all of these reads work again with a single change
instead of one fallback per call site.

Compatibility with older builds:

  • The getter is only installed if the prototype does not already define _serialized.
    Re-injection is a no-op.
  • It has a setter that stores an own property. If a build still assigns
    _serialized in the MsgKey constructor, the assignment works as before and the own
    property shadows the getter. A getter-only accessor would make that assignment throw
    in strict-mode code.

Updated after review: the first version only patched the sendMessage call site. The
prototype getter was suggested in the comments and covers every page-side read at once.

Relationship to #201840

#201840 covers the node-side model (getMessageModel, getChatModel,
Message._patch, downloadMedia). This PR does not replace it. A prototype getter is
inherited, not own, so it is not copied when the page builds the plain model it sends
to Node. With this PR alone, sendMessage returns the Message again, but its
node-side id._serialized can still be undefined. normalizeSerialized in #201840
fixes that part. The two changes are complementary and do not overlap.

Related Issue(s)

Related to #201836 (sendMessage returning an empty message id) and #201862.

I have deliberately not used a closing keyword: those reports do not state the WA Web
build precisely enough for me to confirm they are the same root cause.

Testing Summary

Test Details

  • Original call-site fix, live session (WA Web 2.3000.1046520132, self-chat, no other
    patches): before, sendMessage returned UNDEFINED; after, sendMessage returned Message. The message was delivered in both runs.
  • Prototype getter shape: the same getter (without the setter) has been running in
    production on 2.3000.1046520132 since early September, applied from the application
    side. A reviewer independently reports the same shape fixing sendMessage,
    editMessage and lastReceivedKey on 2.3000.1047868043.
  • This exact patch: exercised with stubbed MsgKey classes covering the three
    shapes: new build (no _serialized, value via toString()), old build assigning an
    own _serialized in a strict-mode constructor (value, descriptor and JSON.stringify
    unchanged; re-assignment still works), and a prototype that already defines the
    property (left untouched). LoadUtils was run twice to check idempotency. I have not
    re-run this exact patch against a live session.

npm run check: ESLint clean. Prettier reports only the pre-existing warning on
index.d.ts, which is also present on unmodified main.

npm test could not be run: the suite requires WWEBJS_TEST_REMOTE_ID and a dedicated
paired account.

Environment

  • Machine OS: Ubuntu 24.04.4 LTS
  • Library Version: 1.34.7 (authored against main @ 942d236)
  • WhatsApp Web Version: 2.3000.1046520132
  • Browser Type and Version: Chrome/146.0.7680.31 (puppeteer bundled Chromium)
  • Node Version: v20.20.2

Type of Change

  • Dependency change (package changes such as removals, upgrades, or additions)
  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Non-code change (documentation, README, etc.)

Checklist

  • My code follows the style guidelines of this project.
  • All new and existing tests pass (npm test). See Test Details: the suite needs a
    dedicated paired test account; npm run check passes.
  • Typings (e.g. index.d.ts) have been updated if necessary. No typing change.
  • Usage examples (e.g. example.js) / documentation have been updated if applicable.
    Not applicable.

@github-actions github-actions Bot added api changes API modifications utility Utility code labels Sep 1, 2026
@emrecirik

Copy link
Copy Markdown

Confirmed on WhatsApp Web 2.3000.1047868043 (whatsapp-web.js 1.34.7, puppeteer 24.38.0, Chrome, Node 22).

Dumping the MsgKey of a just-sent message from the page shows the own properties are fromMe, remote, id, self, $1, with $1 = "true_<redacted>@lid_3EB0…_out" and _serialized undefined — so Msg.get(undefined) resolves to undefined while the message is in fact delivered (it shows up in the chat with ack 3).

One suggestion: instead of fixing this single call site, defining a _serialized getter on window.require('WAWebMsgKey').prototype restores every page-side read at once — this same lookup, editMessage (Msg.get(msg.id._serialized)) and chat.lastReceivedKey._serialized all break the same way on this build. I'm running that shape in production and it fixes all three.

@netobasilio netobasilio changed the title fix(client): sendMessage returns undefined on newer WA Web builds fix: restore MsgKey._serialized on newer WA Web builds Sep 23, 2026
@netobasilio

netobasilio commented Sep 23, 2026 •

Copy link
Copy Markdown
Author

Switched to the prototype getter in 1a94695, with a setter so builds that still assign _serialized in the constructor keep working. The node-side model still needs #201840.

wa Web 2.3000.1043xxx+ no longer exposes `_serialized` on a MsgKey. The
same value is still reachable through the minified `$1` property and
through `toString()`, but the property itself is gone.

`WWebJS.sendMessage` ends by looking the freshly created message up with
`Msg.get(newMsgKey._serialized)`. On these builds that call becomes
`Msg.get(undefined)` and returns nothing, so `Client.sendMessage`
resolves to `undefined` even though the message was actually delivered.
callers that check the return value treat a successful send as a
failure, and no message id is available for tracking acks.

fall back to `$1` and then to `toString()`, keeping `_serialized` first
so older builds take exactly the same path as before.
Replace the single fallback in `WWebJS.sendMessage` with a `_serialized`
getter on `WAWebMsgKey.prototype`, installed when the utils are loaded.
The same missing property also breaks other page-side reads, such as
`editMessage` (`Msg.get(msg.id._serialized)`) and `getChatModel`
(`chat.lastReceivedKey._serialized`). A single getter fixes all of them.

The getter is only installed when the prototype does not already define
`_serialized`. Its setter stores an own property, so builds that still
assign `_serialized` in the constructor behave exactly as before instead
of failing on a getter-only accessor.
@netobasilio
netobasilio force-pushed the fix/sendmessage-msgkey-serialized-fallback branch from 67a2721 to 1a94695 Compare September 23, 2026 17:58
iFallenHunt added a commit to iFallenHunt/api-report-clash that referenced this pull request Sep 24, 2026
…_serialized

No WhatsApp Web 2.3000.1043xxx+ a WAWebMsgKey não tem mais _serialized
(a chave fica em $1/toString()), então o sendMessage fazia
Msg.get(undefined) e resolvia undefined.

- getter _serialized -> toString() no protótipo de WAWebMsgKey
  (baseado em wwebjs/whatsapp-web.js#201901, 1a94695), com try/catch
- getMessageModel copia id._serialized para o Node (cf. #201840)
- patch-package no postinstall com --error-on-fail --error-on-warn
- whatsapp-web.js fixado em 1.34.7
- Dockerfile copia patches/ antes do npm ci

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api changes API modifications utility Utility code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants