Skip to content

[BUG] contacts.update with imgUrl='changed' carries an unresolvable LID — cannot identify which contact changed their profile picture #2598

Description

@iEvolutionPro

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

  1. Connect a Baileys instance via WhatsApp multi-device (makeWASocket, default defaultQueryTimeoutMs).
  2. Establish a chat with contact A .
  3. Have contact A change their WhatsApp profile picture.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions