Skip to content

[BUG] Intermittent sticker media download failures (fetch failed / empty media key) in downloadContentFromMessage #2546

@kaikybrofc

Description

@kaikybrofc

Description

We are observing reproducible media-download failures for stickers in production when using downloadContentFromMessage (indirectly through command handlers).

Two recurring failure modes:

  1. TypeError: fetch failed
  2. Cannot derive from empty media key

This affects sticker conversion flows (sticker -> gif/png) and appears to be tied to specific incoming sticker payload shapes (some valid, some invalid/partial).

Environment

  • Baileys: github:WhiskeySockets/Baileys#v7.0.0-rc10
  • Node.js: v24.14.1
  • npm: 11.11.0
  • OS: Linux 6.8.0-107-generic (Ubuntu)
  • App version: 0.1.8
  • Runtime model: long-running socket process (PM2)

What We Tested

1) Runtime log evidence from command path

Command !togif is correctly parsed and executed, but fails while resolving source sticker media:

  • 2026-05-10T22:56:26Z -> TypeError: fetch failed
  • 2026-05-10T22:57:04Z -> TypeError: fetch failed

After adding defensive handling around source resolution, the command no longer crashes and logs this warning instead:

  • 2026-05-10T22:58:30Z -> sticker convert falhou ao resolver mídia de origem with err.message = fetch failed

So the failure is consistently happening during media retrieval, not during format conversion.

2) Database sampling (message_media) + direct URL fetch tests

We sampled recent sticker records from MySQL (message_media joined with messages) and tested URL fetchability.

Observed URL patterns:

  • Fully qualified https://mmg.whatsapp.net/... -> often downloadable (200)
  • https://a.whatsapp.net -> fetch failed
  • Relative paths like /m1/v/t24/... -> invalid as standalone URL for plain fetch

3) Baileys-level parity test (downloadContentFromMessage)

We replayed recent stored data_json objects through Baileys downloadContentFromMessage(media, 'sticker').

Representative outcomes:

  • Success cases return valid WEBP buffers.
  • Failure cases return:
    • fetch failed
    • Cannot derive from empty media key

This reproduces the same failure signatures seen in production command execution.

Reproduction (Minimal)

  1. Capture recent incoming sticker messages and persist media payload (url, directPath, mediaKey, etc.)
  2. For each payload, call:
const stream = await downloadContentFromMessage(mediaNode, 'sticker')
  1. Observe that some payloads download/decrypt correctly while others fail with:
TypeError: fetch failed

or

Cannot derive from empty media key

Expected Behavior

For sticker payloads that are valid within WhatsApp message flow, Baileys should either:

  1. resolve/reupload/retry media robustly, or
  2. return a more specific structured failure describing which field is missing/invalid (mediaKey, URL host validity, relative URL resolution path, etc.)

Actual Behavior

For a subset of stickers, downloadContentFromMessage fails non-deterministically from application perspective due to payload shape:

  • Host/URL variants that are not directly fetchable
  • Payloads where media key material appears insufficient for decryption

Additional Technical Notes

  • In our sample set, this is not universal failure: many stickers in same timeframe work fine.
  • Failures correlate strongly with specific URL/payload variants rather than command logic.
  • We currently mitigate at app level by falling back and returning user-friendly messages, but root cause remains at media retrieval/decryption boundary.

Questions for Maintainers

  1. Is https://a.whatsapp.net (or relative /m1/...) expected to appear for sticker media nodes in this version?
  2. Is there a recommended canonical normalization path before downloadContentFromMessage for these nodes?
  3. Is there a supported media-reupload retry path specifically for sticker downloads in this scenario?
  4. Are there known regressions around v7.0.0-rc10 + Node 24 for sticker fetch/decrypt?

Optional: We can provide redacted payload samples

We can share several redacted data_json payloads (working vs failing) if useful for triage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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