openclaw - ✅(Solved) Fix message tool silently drops local file paths and external URLs in the media field [1 pull requests, 1 participants]

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…
GitHub stats
openclaw/openclaw#63493Fetched 2026-04-09 07:53:07
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
cross-referenced ×1referenced ×1subscribed ×1

When an agent calls the message tool and populates the media parameter with a local file path (e.g. /Users/rootzeye/.openclaw/media/image-search/00924dce1ad9.jpg) or a direct HTTPS image URL, the gateway accepts the payload but silently strips the media attachment and sends the message as hasMedia: False text-only.

Root Cause

When an agent calls the message tool and populates the media parameter with a local file path (e.g. /Users/rootzeye/.openclaw/media/image-search/00924dce1ad9.jpg) or a direct HTTPS image URL, the gateway accepts the payload but silently strips the media attachment and sends the message as hasMedia: False text-only.

Fix Action

Fix / Workaround

The message tool should detect that media contains a valid local file path or direct URL, read the file, and dispatch it as a media attachment (e.g., via Baileys image payload).

PR fix notes

PR #63505: fix(outbound): accept message tool media alias for sends #63493

Description (problem / solution / changelog)

Summary

  • Problem: The message tool uses a media field for local paths and HTTPS URLs, but several outbound paths only normalized or forwarded mediaUrl / mediaUrls. That could strip attachments so WhatsApp (and similar) logged hasMedia: false and sent text-only.
  • Why it matters: Agents cannot reliably deliver photos/files from MCP or disk when the payload only carried media.
  • What changed: Treat media as an alias of mediaUrl in Plugin SDK normalization, reply payload delivery normalization, sendMessage, gateway send (schema + handler), and outbound send service fallback from ctx.params.media.
  • What did NOT change (scope boundary): No WhatsApp/Baileys-specific hacks; no changes to security CODEOWNERS paths; no unrelated refactors.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Fixes #63493
  • Related #63493

User-visible / Behavior Changes

  • Gateway send accepts an optional media field as an alias for mediaUrl.
  • Outbound delivery and sendMessage honor media when mediaUrl is absent, aligning with the message tool schema.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Linux (CI / local dev)
  • Runtime/container: Node 22+ / Vitest
  • Model/provider: N/A
  • Integration/channel (if any): Covered generically via gateway send + payload normalization tests (not live WhatsApp)
  • Relevant config (redacted): N/A

Steps

  1. Call gateway send with to, channel, idempotencyKey, and media set to a URL (no mediaUrl).
  2. Run unit tests for normalizeReplyPayloadsForDelivery with a payload carrying media only.
  3. Run normalizeOutboundReplyPayload tests for mediamediaUrl mapping.

Expected

  • Delivery receives payloads with mediaUrl populated (or equivalent merged mediaUrls).
  • No silent drop of attachments solely because the field was named media.

Actual

  • Added/adjusted tests; targeted pnpm test on touched *.test.ts files passed; scripts/committer run completed pnpm check green for the committed tree.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: Unit tests for src/infra/outbound/payloads.test.ts, src/gateway/server-methods/send.test.ts, src/plugin-sdk/reply-payload.test.ts; commit hook pnpm check after scripts/committer.
  • Edge cases checked: media + existing mediaUrl (explicit mediaUrl wins); promotion removes stray media key after alias in delivery normalization.
  • What I did not verify: Live WhatsApp multi-device send against a real session.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • Revert the PR / restore prior main for the listed files under src/plugin-sdk/reply-payload.ts, src/infra/outbound/payloads.ts, src/infra/outbound/message.ts, src/infra/outbound/outbound-send-service.ts, src/gateway/server-methods/send.ts, src/gateway/protocol/schema/agent.ts.
  • Known bad symptoms: unexpected preference of media over mediaUrl if both differ (intended: explicit mediaUrl wins where implemented).

Risks and Mitigations

  • Risk: Callers pass both media and mediaUrl with different values.
    • Mitigation: Alias layers prefer explicit mediaUrl / non-empty mediaUrls over media where documented in code paths touched.

Changed files

  • src/gateway/protocol/schema/agent.ts (modified, +2/-0)
  • src/gateway/server-methods/send.test.ts (modified, +54/-0)
  • src/gateway/server-methods/send.ts (modified, +7/-1)
  • src/infra/outbound/message.test.ts (modified, +17/-0)
  • src/infra/outbound/message.ts (modified, +15/-3)
  • src/infra/outbound/outbound-send-service.ts (modified, +3/-0)
  • src/infra/outbound/payloads.test.ts (modified, +28/-0)
  • src/infra/outbound/payloads.ts (modified, +20/-1)
  • src/plugin-sdk/reply-payload.test.ts (modified, +31/-0)
  • src/plugin-sdk/reply-payload.ts (modified, +3/-1)

Code Example

{
  "action": "send",
  "channel": "whatsapp",
  "target": "[email protected]",
  "media": "/Users/rootzeye/.openclaw/media/image-search/abc.jpg",
  "caption": "Test"
}
RAW_BUFFERClick to expand / collapse

Summary

When an agent calls the message tool and populates the media parameter with a local file path (e.g. /Users/rootzeye/.openclaw/media/image-search/00924dce1ad9.jpg) or a direct HTTPS image URL, the gateway accepts the payload but silently strips the media attachment and sends the message as hasMedia: False text-only.

Environment

  • OpenClaw version: 2026.4.8 (9ece252)
  • Channel: WhatsApp (Multi-Device)
  • Tools involved: Custom MCP returning local file path -> message tool

Reproduction

  1. Agent obtains a valid local file path to an image (e.g., from an MCP server or read tool).
  2. Agent calls message tool:
{
  "action": "send",
  "channel": "whatsapp",
  "target": "[email protected]",
  "media": "/Users/rootzeye/.openclaw/media/image-search/abc.jpg",
  "caption": "Test"
}
  1. The gateway logs sending message {'jid': '...', 'hasMedia': False} and delivers the caption as text only.

Expected Behavior

The message tool should detect that media contains a valid local file path or direct URL, read the file, and dispatch it as a media attachment (e.g., via Baileys image payload).

Note

This prevents agents from sending real photos retrieved from the web or filesystem (like a restaurant dish or a dossier photo). Currently, only synthetic images generated internally by image_generate successfully resolve to hasMedia: True in the outbound pipeline.

extent analysis

TL;DR

The message tool likely needs to be updated to properly handle local file paths and direct HTTPS image URLs in the media parameter.

Guidance

  • Verify that the media parameter is being passed correctly to the message tool by checking the payload before it is sent.
  • Check the documentation for the message tool to see if there are any specific requirements for handling local file paths or direct HTTPS image URLs.
  • Test sending a message with a synthetic image generated by image_generate to see if the issue is specific to external images.
  • Consider adding logging to the message tool to see if it is attempting to read the file or access the URL, and if so, what errors it may be encountering.

Example

No code snippet is provided as the issue does not imply a specific code change.

Notes

The issue may be specific to the message tool's handling of external images, and further investigation is needed to determine the root cause.

Recommendation

Apply a workaround, such as modifying the message tool to handle local file paths and direct HTTPS image URLs correctly, as the root cause of the issue is likely a limitation in the tool's current implementation.

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