Environment
- Baileys version:
7.0.0-rc13
- Node.js:
v18.20.5
- OS: Linux
- Account login_type: Qr
Summary
When a contact updates their profile picture, Baileys emits contacts.update with imgUrl: 'changed', but the id field is not the same LID that appears in the contact's incoming messages. The notified LID does not resolve via lidMapping.getPNForLID() to the correct phone number, making it impossible to know which contact actually changed their picture.
Source of the bug
In src/Socket/messages-recv.ts case 'picture' line 1075:
case 'picture':
const setPicture = getBinaryNodeChild(node, 'set');
const delPicture = getBinaryNodeChild(node, 'delete');
// TODO: WAJIDHASH stuff proper support inhouse <-- author's own TODO
ev.emit('contacts.update', [
{
id: jidNormalizedUser(node?.attrs?.from) || (setPicture || delPicture)?.attrs?.hash || '',
imgUrl: setPicture ? 'changed' : 'removed'
}
]);
The node.attrs.from carries an LID that is opaque (a "privacy LID" / WAJIDHASH wrapper) rather than the contact's canonical LID used in messages. There's a // TODO: WAJIDHASH stuff proper support inhouse already acknowledging the gap.
Reproduction
- Connect a Baileys instance via WhatsApp multi-device (
makeWASocket, default defaultQueryTimeoutMs).
- Establish a chat with contact A .
- Have contact A change their WhatsApp profile picture.
- Listen to
ev.on('contacts.update', ...).
Expected behavior
The emitted contacts.update should carry the same LID that appears in the contact's messages, so applications can correlate the change with their cached contact and invalidate/refresh that contact's picture.
Actual behavior
The emitted event carries a different, unresolvable LID:
[{
"id": "xxxxxxxxxxxxxxx@lid",
"imgUrl": "changed"
}]
lidMapping.getPNForLID returns the bot's own phone number (the connected account, not contact A), making it impossible to associate the change to contact A.
The notification node also has no <user> / <participant> child carrying the real JID — only the privacy LID in attrs.from and a 4-char picture hash (RdSV) in <set hash="...">.
Impact
Any application that caches profile pictures cannot invalidate them per-contact when this event fires.
In our case we ended up implementing brute-force invalidation of every cached imgUrl in our Redis store, which is wasteful but the only correct alternative.
Notes/Updates
- After testing, we discovered this only happens for contacts that are not saved/registered in the account's contact list.
- When the contact is added to the account contacts, the notification node includes the proper jid and lid in the node body, allowing the update to be correctly associated with the contact.
Environment
7.0.0-rc13v18.20.5Summary
When a contact updates their profile picture, Baileys emits
contacts.updatewithimgUrl: 'changed', but theidfield is not the same LID that appears in the contact's incoming messages. The notified LID does not resolve vialidMapping.getPNForLID()to the correct phone number, making it impossible to know which contact actually changed their picture.Source of the bug
In
src/Socket/messages-recv.tscase 'picture'line 1075:The
node.attrs.fromcarries an LID that is opaque (a "privacy LID" / WAJIDHASH wrapper) rather than the contact's canonical LID used in messages. There's a// TODO: WAJIDHASH stuff proper support inhousealready acknowledging the gap.Reproduction
makeWASocket, defaultdefaultQueryTimeoutMs).ev.on('contacts.update', ...).Expected behavior
The emitted
contacts.updateshould carry the same LID that appears in the contact's messages, so applications can correlate the change with their cached contact and invalidate/refresh that contact's picture.Actual behavior
The emitted event carries a different, unresolvable LID:
[{ "id": "xxxxxxxxxxxxxxx@lid", "imgUrl": "changed" }]lidMapping.getPNForLIDreturns the bot's own phone number (the connected account, not contact A), making it impossible to associate the change to contact A.The notification node also has no
<user>/<participant>child carrying the real JID — only the privacy LID inattrs.fromand a 4-char picture hash (RdSV) in<set hash="...">.Impact
Any application that caches profile pictures cannot invalidate them per-contact when this event fires.
In our case we ended up implementing brute-force invalidation of every cached
imgUrlin our Redis store, which is wasteful but the only correct alternative.Notes/Updates