[BUG] Bot sends to a LID group are permanently stuck at "Waiting for this message" for some devices — sender-key-memory is never invalidated (baileys 7.0.0-rc.9)
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 38/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- node.js, postgresql, redis, typescript
- Domain
- api, backend, backend-api-design, databases
Research direction
Start with issue #2705 and the getMessage() implementation shown in dist/main.js, then review the Baileys sender-key handling described in src/Socket/messages-send.ts and sendMessagesAgain in src/Socket/messages-recv.ts. Done requires an agreed scope for miss/error handling, sender-key recovery, reset controls, and group-send observability, with tests or verification for the selected changes.
Written by the indexing model from the issue text.
Description
Welcome!
- Yes, I have searched for similar issues on GitHub and found none.
What did you do?
We use Evolution API to post automated alerts into a WhatsApp group, via POST /message/sendText/{instance} addressed to the group JID. The group is fully LID-addressed: ~14 participants, all @lid.
Self-hosted v2.3.7 on systemd (not Docker), Debian 12, Node v20.20.2, Postgres 15, Redis-backed Baileys auth state.
What did you expect?
Every member of the group receives the message and can read it — the same way everyone reads messages posted by a human in that same group.
What did you observe instead of what you expected?
The API accepts every send (HTTP 200, nothing in the logs), but a subset of members never sees the content — only "Waiting for this message. This may take a while.", indefinitely, for more than a week. In the same group:
- Android members read everything normally;
- iPhone members read nothing the bot sends;
- messages posted by humans in that group are read by everyone, including the affected iPhones.
So it is not the group, not the message body, not the pairing.
What we measured. The Baileys state key sender-key-memory-<group>@g.us — a jid → bool map of "who I already sent this group's SenderKey to" — is always 100% true: 29, 22, 30 and 22 device entries on four separate occasions, always zero false. It never self-clears.
Deleting that single field restores delivery, confirmed on the affected users' handsets, 3 out of 3 times (2026-08-03, 2026-08-08, 2026-08-19), and it breaks again within days — 4 events in 21 days. After the deletion the map is rebuilt with fewer entries than the frozen one (30 → 21), so part of the frozen map was dead bookkeeping.
One extra data point that pins the mechanism: an affected iPhone user created a new WhatsApp Business registration and immediately started receiving the bot's group messages, with no change on our side. A fresh registration is a device not yet marked in that map, so it receives the SenderKeyDistributionMessage on the next send; devices already marked true never do.
Screenshots/Videos
No response
Which version of the API are you using?
2.3.7
What is your environment?
Linux
Other environment specifications
Debian GNU/Linux 12 (bookworm), Node v20.20.2, systemd service (not Docker)
baileys 7.0.0-rc.9 — the pin in this repository's package.json (same on main and on the 2.4.0-rc2 tag)
Postgres 15; Redis for Baileys auth state and cache
CACHE_REDIS_ENABLED=true, CACHE_LOCAL_ENABLED=false, CACHE_REDIS_TTL=604800
Target group fully LID-addressed: the 22 device JIDs in its sender-key-memory are all @lid, zero @s.whatsapp.net
If applicable, paste the log output
The application log is clean — that is part of the problem. What follows is state measured directly, with identifiers redacted.
# the group's sender-key bookkeeping map, measured on four occasions
2026-08-03 29 devices, 29 true, 0 false
2026-08-08 22 devices, 22 true, 0 false
2026-08-19 30 devices, 30 true, 0 false
2026-08-24 22 devices, 22 true, 0 false <- before clearing
# after deleting that one field: no key material touched, session intact
group sender-key-memory maps : 0
sender-key-* (material) : 2
session-* : 141
pre-key-* : 1686
Instance.connectionStatus : open
# getMessage() in the running 2.3.7 bundle (dist/main.js) -- see #2705
async getMessage(e,t=!1){try{ ...$queryRaw`SELECT * FROM "Message" WHERE "instanceId"=... AND "key"->>'id'=${e.id}`;
if(t)return o[0]; ... return o[0].message }catch{ return {conversation:""} }}
# Message.status for GROUP sends, last 24h
PENDING | 155 (1-1 @lid progresses normally to SERVER_ACK / DELIVERY_ACK / READ)
Additional Notes
Root cause is upstream in baileys — but it reaches users through this project's pin
In baileys@7.0.0-rc.9 and in current master — identical on this point — src/Socket/messages-send.ts reads that map and only ever writes true into it; the comment // on participant change in group, we should do sender memory manipulation is still unimplemented. The only invalidation in the whole library is in sendMessagesAgain (src/Socket/messages-recv.ts):
if (isJidGroup(remoteJid)) {
await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } })
}
So for groups the retry receipt is not one recovery path among several — it is the only one.
Upstream this is WhiskeySockets/Baileys#2704 (same three root causes: map never invalidated; identity-change notification discarded when the socket was offline; server-side participant-hash correction commented out). It was closed by the stale bot with no maintainer reply. The PRs that fix it — WhiskeySockets/Baileys#2711 and #2748 — have been open and stale since July. WhiskeySockets/Baileys#2297 is the same symptom reported specifically for iOS recipients, open since January.
And #2705 in this repository makes it permanent
getMessage() returns { conversation: '' } on any exception — a truthy object — so Baileys relays an empty envelope and consumes one of the recipient's limited retries. On a miss the query returns [], so rows[0].message?.… throws and lands in the same catch: "not found" and "database error" converge on the same empty envelope, silently. Since the retry receipt is the only thing that can clear sender-key-memory for a group, burning the retries turns a transient decryption failure into permanent blindness for that device.
Why "just upgrade" is not an answer
Verified 2026-08-24: main and the 2.4.0-rc2 tag both pin baileys: 7.0.0-rc.9, the version we already run. And baileys has no stable 7.x — the newest is 7.0.0-rc14 (2026-07-29), which does not fix this, since the identity-change invalidation exists only in the unmerged PRs. Evolution users have nowhere to upgrade to.
Requests
- Fix #2705 — cheapest and highest-leverage change here, because it restores the only recovery path that exists for groups. On top of the proposed
return undefined: handle the miss separately (if (!rows.length) return undefined) so a genuine database failure can be logged instead of masquerading as a cache miss, and log atwarnwhengetMessagemisses. - Mitigate in the Evolution layer, which owns the call into
relayMessage: clearsender-key-memoryfor the group JID before sending (or every N minutes, or whengroupMetadatachanges). Suggested surface: an opt-inGROUP_SENDER_KEY_RESET=always|interval|off. Cost is redistributing the SenderKey to the group's devices on the next send — 22 devices in our case. - Expose an endpoint/flag to reset a group's sender-key state without restarting the instance and without a manual
HDELin Redis. Today the only route requires direct datastore access, which many hosted users do not have. We currently clear the field hourly from cron as a stop-gap; that should not be necessary. - Secondary observability bug:
Message.statusfor group sends never leavesPENDINGon this installation (155 of 155 in the last 24 h), while 1-1@lidprogresses normally.PENDINGdoes not prove non-delivery — messages we confirmed as delivered also sit atPENDING— and that is exactly why the field is useless as an oracle and why this stayed invisible for weeks.
- Dominant language
- TypeScript
- Stars
- 9.6k
- Forks
- 7.3k
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from evolution-foundation/evolution-api
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
evolution-foundation/evolution-api#2700 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
All issues in evolution-foundation/evolution-api
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
ontola/atomic-server#1625 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
melgarafael/DeskcommCRM#1451 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 82/100
-
bug via-triage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bot:ai-assisted component:compact-js status:untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
midnightntwrk/midnight-sdk#403 ·