From c3a6092beaf20dd1653ad7449bf394070c9bd545 Mon Sep 17 00:00:00 2001 From: Carlos Alaniz Date: Thu, 16 Jul 2026 16:57:45 -0500 Subject: [PATCH] fix: skip LID chats that fail IndexedDB group metadata lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace Promise.all in getChats() with sequential try/catch so one bad chat does not discard every chat - Wrap groupMetadata.update(chatWid) in try/catch — LID-based chat IDs (@lid) fail IndexedDB lookup, causing DataError - Add getMsgKeyId() helper that falls back _serialized -> $1 to tolerate WhatsApp Web's recent rename of the serialized property - Use getMsgKeyId() in sendMessage, editMessage, getMessageModel and getChatModel instead of raw ._serialized access - Restore _serialized on msg.id in getMessageModel so downstream consumers of message.id._serialized keep working --- src/util/Injected/Utils.js | 68 +++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/src/util/Injected/Utils.js b/src/util/Injected/Utils.js index dfa30a5..8be2759 100644 --- a/src/util/Injected/Utils.js +++ b/src/util/Injected/Utils.js @@ -582,7 +582,7 @@ exports.LoadUtils = () => { return window .require('WAWebCollections') - .Msg.get(newMsgKey._serialized); + .Msg.get(window.WWebJS.getMsgKeyId(newMsgKey)); }; window.WWebJS.editMessage = async (msg, content, options = {}) => { @@ -625,7 +625,9 @@ exports.LoadUtils = () => { await window .require('WAWebSendMessageEditAction') .sendMessageEdit(msg, content, internalOptions); - return window.require('WAWebCollections').Msg.get(msg.id._serialized); + return window + .require('WAWebCollections') + .Msg.get(window.WWebJS.getMsgKeyId(msg.id)); }; window.WWebJS.toStickerData = async (mediaInfo) => { @@ -834,6 +836,20 @@ exports.LoadUtils = () => { }); } + // The rename reaches the serialized model too: `msg.id` comes back carrying `$1` and no + // `_serialized`, so every consumer of `message.id._serialized` — including this library's own + // Message structure and anything keyed on a message id — silently receives undefined. Restore + // it here, where `msg.id.remote` is already normalised, so the whole downstream surface keeps + // working rather than each caller having to know about `$1`. + if (typeof msg.id === 'object' && msg.id._serialized == null) { + const serializedId = window.WWebJS.getMsgKeyId(msg.id); + if (serializedId) { + msg.id = Object.assign({}, msg.id, { + _serialized: serializedId, + }); + } + } + delete msg.pendingAckUpdate; return msg; @@ -917,12 +933,34 @@ exports.LoadUtils = () => { }; }; + /** + * The serialized id of a message key, tolerating WhatsApp Web having renamed the key's + * `_serialized` property to `$1`. Reading the old name now returns `undefined`, which reaches + * IndexedDB as a `.get(undefined)` and throws + * `DataError: Failed to execute 'get' on 'IDBObjectStore': No key or key range specified.` + * `_serialized` is preferred so nothing changes wherever it is still present (chat ids, for + * example, are unaffected by the rename). Returns undefined when neither exists, so callers can + * skip the lookup instead of querying a store with a nullish key. + * @param {Object} key a message key, e.g. `chat.lastReceivedKey` or a raw `msg.id` + * @returns {string|undefined} + */ + window.WWebJS.getMsgKeyId = (key) => + key?._serialized ?? key?.$1 ?? undefined; + window.WWebJS.getChats = async () => { const chats = window.require('WAWebCollections').Chat.getModelsArray(); - const chatPromises = chats.map((chat) => - window.WWebJS.getChatModel(chat), - ); - return await Promise.all(chatPromises); + + // Process each chat individually — one failure should not discard every chat + const results = []; + for (const chat of chats) { + try { + const model = await window.WWebJS.getChatModel(chat); + if (model) results.push(model); + } catch { + // skip chats that fail serialization (e.g. LID-based group metadata issues) + } + } + return results; }; window.WWebJS.getChannels = async () => { @@ -957,7 +995,12 @@ exports.LoadUtils = () => { const groupMetadata = window.require('WAWebCollections').GroupMetadata || window.require('WAWebCollections').WAWebGroupMetadataCollection; - await groupMetadata.update(chatWid); + try { + await groupMetadata.update(chatWid); + } catch { + // LID-based chat IDs may not be found in IndexedDB — skip group metadata + model.groupMetadata = null; + } const { toPn } = window.require('WAWebLidMigrationUtils'); const serializedMetadata = chat.groupMetadata.serialize(); for (const p of serializedMetadata.participants || []) { @@ -981,16 +1024,17 @@ exports.LoadUtils = () => { model.lastMessage = null; if (model.msgs && model.msgs.length) { - const lastMessage = chat.lastReceivedKey + const lastReceivedKeyId = window.WWebJS.getMsgKeyId( + chat.lastReceivedKey, + ); + const lastMessage = lastReceivedKeyId ? window .require('WAWebCollections') - .Msg.get(chat.lastReceivedKey._serialized) || + .Msg.get(lastReceivedKeyId) || ( await window .require('WAWebCollections') - .Msg.getMessagesById([ - chat.lastReceivedKey._serialized, - ]) + .Msg.getMessagesById([lastReceivedKeyId]) )?.messages?.[0] : null; lastMessage &&