openclaw - 💡(How to fix) Fix Bug: WhatsApp Inbound Image Fails on Second Read (UUID Mismatch from Double-Save)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

OpenClaw v2026.5.27 experiences a critical bug where images sent via the WhatsApp channel cannot be consistently read by the image tool after their initial access. Attempts to read the same image a second time using its media://inbound/ ID fail with the error "media ID does not resolve to a file".

Error Message

Error: resolveMediaBufferPath: media ID does not resolve to a file: "F5BBDBB6-591E-47C5-8167-FB9C8D5FB04D"

Root Cause

The bug is caused by a UUID mismatch between two save operations in the media handling pipeline:

1. The Double-Save Problem

Media files go through two save operations with two different UUIDs:

  • Save #1 (WhatsApp Plugin):
    @openclaw/whatsapp downloads the image from WhatsApp's servers and calls saveMediaStream() with subdir="inbound". The file is saved with its own UUID, e.g. ebaaf762-63e3-4210-80c8-52bc50ae698c.jpg.

  • Save #2 (Attachment Normalizer):
    The Gateway's attachment normalizer (attachment-normalize) processes the inbound message, reads the file from step 1, extracts its base64 content, then re-saves it via saveMediaBuffer(). This generates a new UUID, e.g. F5BBDBB6-591E-47C5-8167-FB9C8D5FB04D. The media://inbound/ URI injected into the agent's context uses this new UUID.

2. The Ephemeral File Problem

The file created by Save #2 is ephemeral — it gets cleaned up after being consumed. The first image tool call succeeds because the file still exists at that point. But a subsequent call (e.g., from a subagent) attempts to access the same URI after the file has been cleaned up — and fails.

The original file from the WhatsApp plugin (ebaaf762-*) still exists on disk, but the media://inbound/ URI points to the ephemeral copy's UUID, not the original.

3. Source Code Evidence

In attachment-normalize (pseudocode):

savedMedia = await saveMediaBuffer(buffer, finalMime, "inbound", maxBytes, ...);
const mediaRef = `media://inbound/${savedMedia.id}`;  // ← Uses NEW UUID

In store (resolveMediaBufferPath):

async function resolveMediaBufferPath(id, subdir = "inbound") {
  const relativePath = resolveMediaRelativePath(id, subdir, "resolveMediaBufferPath");
  if (!opened?.stat.isFile())
    throw new Error(
      `resolveMediaBufferPath: media ID does not resolve to a file: ${JSON.stringify(id)}`
    );
}

4. Key Mismatch

File saved by WhatsApp plugin:   ebaaf762-63e3-4210-80c8-52bc50ae698c.jpg  ✅ EXISTS
Media ID in failing tool call:   F5BBDBB6-591E-47C5-8167-FB9C8D5FB04D       ❌ NOT FOUND

Code Example

Error: resolveMediaBufferPath: media ID does not resolve to a file: "F5BBDBB6-591E-47C5-8167-FB9C8D5FB04D"

---

savedMedia = await saveMediaBuffer(buffer, finalMime, "inbound", maxBytes, ...);
const mediaRef = `media://inbound/${savedMedia.id}`;  // ← Uses NEW UUID

---

async function resolveMediaBufferPath(id, subdir = "inbound") {
  const relativePath = resolveMediaRelativePath(id, subdir, "resolveMediaBufferPath");
  if (!opened?.stat.isFile())
    throw new Error(
      `resolveMediaBufferPath: media ID does not resolve to a file: ${JSON.stringify(id)}`
    );
}

---

File saved by WhatsApp plugin:   ebaaf762-63e3-4210-80c8-52bc50ae698c.jpgEXISTS
Media ID in failing tool call:   F5BBDBB6-591E-47C5-8167-FB9C8D5FB04DNOT FOUND
RAW_BUFFERClick to expand / collapse

Description

OpenClaw v2026.5.27 experiences a critical bug where images sent via the WhatsApp channel cannot be consistently read by the image tool after their initial access. Attempts to read the same image a second time using its media://inbound/ ID fail with the error "media ID does not resolve to a file".

Steps to Reproduce

  1. Send an image to the OpenClaw agent via WhatsApp.
  2. In the agent session, use the image tool to read the newly received image (e.g., image(image="media://inbound/<MEDIA_ID>")). This first read typically succeeds.
  3. Attempt to use the image tool again on the same media://inbound/<MEDIA_ID> in a subsequent turn or subagent context.

Expected Behavior

The image tool should be able to consistently read an inbound image using its assigned media://inbound/<MEDIA_ID> for the duration of the session, or at least until explicitly removed or garbage-collected with a reasonable TTL.

Observed Behavior

After the first successful read of a WhatsApp inbound image, subsequent attempts to read the same image using its media://inbound/<MEDIA_ID> fail with:

Error: resolveMediaBufferPath: media ID does not resolve to a file: "F5BBDBB6-591E-47C5-8167-FB9C8D5FB04D"

Root Cause Analysis

The bug is caused by a UUID mismatch between two save operations in the media handling pipeline:

1. The Double-Save Problem

Media files go through two save operations with two different UUIDs:

  • Save #1 (WhatsApp Plugin):
    @openclaw/whatsapp downloads the image from WhatsApp's servers and calls saveMediaStream() with subdir="inbound". The file is saved with its own UUID, e.g. ebaaf762-63e3-4210-80c8-52bc50ae698c.jpg.

  • Save #2 (Attachment Normalizer):
    The Gateway's attachment normalizer (attachment-normalize) processes the inbound message, reads the file from step 1, extracts its base64 content, then re-saves it via saveMediaBuffer(). This generates a new UUID, e.g. F5BBDBB6-591E-47C5-8167-FB9C8D5FB04D. The media://inbound/ URI injected into the agent's context uses this new UUID.

2. The Ephemeral File Problem

The file created by Save #2 is ephemeral — it gets cleaned up after being consumed. The first image tool call succeeds because the file still exists at that point. But a subsequent call (e.g., from a subagent) attempts to access the same URI after the file has been cleaned up — and fails.

The original file from the WhatsApp plugin (ebaaf762-*) still exists on disk, but the media://inbound/ URI points to the ephemeral copy's UUID, not the original.

3. Source Code Evidence

In attachment-normalize (pseudocode):

savedMedia = await saveMediaBuffer(buffer, finalMime, "inbound", maxBytes, ...);
const mediaRef = `media://inbound/${savedMedia.id}`;  // ← Uses NEW UUID

In store (resolveMediaBufferPath):

async function resolveMediaBufferPath(id, subdir = "inbound") {
  const relativePath = resolveMediaRelativePath(id, subdir, "resolveMediaBufferPath");
  if (!opened?.stat.isFile())
    throw new Error(
      `resolveMediaBufferPath: media ID does not resolve to a file: ${JSON.stringify(id)}`
    );
}

4. Key Mismatch

File saved by WhatsApp plugin:   ebaaf762-63e3-4210-80c8-52bc50ae698c.jpg  ✅ EXISTS
Media ID in failing tool call:   F5BBDBB6-591E-47C5-8167-FB9C8D5FB04D       ❌ NOT FOUND

Environmental Verification (Not an Environment Issue)

All environmental checks passed:

  • Disk space: 101 GB free (healthy)
  • Media directory permissions: correct (drwx------ admin:admin)
  • mediaMaxMb config: 50 MB (file was only 167 KB — well within limit)
  • Temp directories: accessible and writable
  • WhatsApp channel config: correctly configured

This is a confirmed code bug, not a configuration or disk-space issue.

Affected Components

  • OpenClaw Core Media Handling Pipeline (store, attachment-normalize)
  • @openclaw/whatsapp plugin (inbound media processing)
  • image tool interaction with inbound media
  • Version: v2026.5.27 (commit 27ae826)

Proposed Fixes

Option A: Avoid Double-Save (Ideal Fix)
The attachment normalizer should NOT re-save media files that already exist on disk from channel plugins. Instead:

  1. Detect that mediaPath already points to a valid file in the media store
  2. Extract the UUID from the existing filename
  3. Use that UUID in the media://inbound/ URI directly

Option B: Propagate Original UUID
When the WhatsApp plugin saves media via saveMediaStream(), propagate the returned UUID through the entire pipeline so the media://inbound/ URI uses the original, persistent UUID.

Option C: Preserve Ephemeral Files Longer
Extend the TTL or reference count on re-saved media so they survive beyond the first tool access.

Environment

  • OpenClaw Version: v2026.5.27 (27ae826)
  • Channel: WhatsApp
  • OS: Linux (Gateway Host)
  • Config: mediaMaxMb = 50, WhatsApp channel enabled

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Bug: WhatsApp Inbound Image Fails on Second Read (UUID Mismatch from Double-Save)