WhatsApp Auto-Reply Inline MEDIA:/path Fails to Deliver Media
Assistant-generated inline MEDIA:/absolute/path payloads in WhatsApp auto-replies do not deliver attachments despite the same file succeeding via manual openclaw message send --media.
๐ Symptoms
Primary Manifestation
When the assistant’s final response contains an inline MEDIA:/absolute/path URI, the text portion of the reply may arrive in WhatsApp, but the media attachment is silently dropped.
Observed Behavior in Session JSONL
Assistant turn payload (final): MEDIA:/home/flconnect/.openclaw/workspace/exports/images/evolution_ca_ttc_2026_par_mois.png
Result:
- File exists at the specified path (verified)
- No media delivery in WhatsApp DM
- Text acknowledgment may or may not arrive
Working Manual Alternative
bash
openclaw message send
–channel whatsapp
–target +212600000000
–media /home/flconnect/.openclaw/workspace/exports/images/evolution_ca_ttc_2026_par_mois.png
–message “test”
Result: Same file delivered successfully with caption.
Diagnostic Evidence
| Check | Manual Path | Auto-Reply Path |
|---|---|---|
| File existence | โ Confirmed | โ Confirmed |
| WhatsApp API auth | โ Valid | โ Valid |
| Media upload | โ Success | โ Silent failure |
| Attachment delivery | โ Received | โ Not received |
CLI Diagnostics
bash
Verify file exists and is accessible
ls -la /home/flconnect/.openclaw/workspace/exports/images/evolution_ca_ttc_2026_par_mois.png
Expected: -rw-r–r– [size] [date] [filename]
Check OpenClaw session logs
openclaw logs –session recent –format json | jq ‘.[] | select(.type==“assistant”) | .content’ | grep -i media
May show: MEDIA:/home/… but no upload confirmation
๐ง Root Cause
Architectural Divergence: Two Media Dispatch Paths
OpenClaw v2026.4.14 exposes two distinct media delivery code paths:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ AUTO-REPLY PATH (BROKEN) โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ Assistant Response โ โ โ โ โ โผ โ โ Assistant Handler parses response text โ โ โ โ โ โผ โ โ Inline MEDIA:/path extraction โ โ โ โ โ โผ โ โ Media Processor (v2026.4.14 regression) โ โ โ โ โ โผ โ โ WhatsApp Channel Adapter โ โ โ โ โ โผ โ โ X Media Upload API โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ MANUAL SEND PATH (WORKING) โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ openclaw message send –media โ โ โ โ โ โผ โ โ CLI Media Resolver โ โ โ โ โ โผ โ โ Direct Channel Adapter call โ โ โ โ โ โผ โ โ WhatsApp Channel Adapter โ โ โ โ โ โผ โ โ X Media Upload API โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Probable Regression: Media Processor Change in v2026.4.11โv2026.4.14
The commit introducing the regression likely modified the MediaProcessor class in src/core/media-processor.ts or equivalent:
Suspected Code Path Failure:
typescript // LIKELY BROKEN: Assistant handler inline MEDIA: parsing async processAssistantMedia(response: string): Promise<MediaAttachment[]> { const mediaUris = this.extractMediaUris(response); // Extracts MEDIA:/path
for (const uri of mediaUris) {
// BUG: v2026.4.14 changed path normalization
const normalizedPath = this.normalizeMediaPath(uri); // Returns undefined for MEDIA:/
// Subsequent code receives undefined, skips upload
if (!normalizedPath) continue;
await this.uploadMedia(normalizedPath);
}
}
Contrast with Working Manual Path:
typescript
// WORKING: CLI path bypasses broken normalization
async sendMediaViaCLI(filePath: string): Promise
await this.whatsappAdapter.uploadMedia(absolutePath);
}
Specific Failure Modes
- Path Scheme Mismatch: The `MEDIA:/` URI scheme is not recognized by the media processor's normalization routine, which expects `file:///` or bare filesystem paths.
- Absolute Path Stripping: The processor incorrectly strips the leading `/` from absolute paths within `MEDIA:/path`, producing relative paths that fail validation.
- Upload Timeout: The async upload for auto-replied media is silently awaited but the promise chain is broken, causing a fire-and-forget that never resolves.
- Channel Adapter Contract Change: The WhatsApp adapter's `sendMedia()` method signature changed between v2026.4.11 and v2026.4.14, and the auto-reply handler uses an outdated interface.
๐ ๏ธ Step-by-Step Fix
Option A: Patch via Configuration Override (Immediate Workaround)
Force the assistant to use the working CLI-style path by configuring response formatting:
bash
Set environment variable to force absolute file:// URIs instead of MEDIA:/
export OPENCLAW_MEDIA_URI_SCHEME=“file”
Restart OpenClaw service
sudo systemctl restart openclaw
Before:
Assistant outputs: MEDIA:/home/flconnect/.openclaw/workspace/exports/images/chart.png Result: Media not delivered
After:
Assistant outputs: file:///home/flconnect/.openclaw/workspace/exports/images/chart.png Result: Media delivered successfully (if fix works)
Option B: Patch the Media Processor Source
Edit src/core/media-processor.ts (or equivalent):
typescript // FIND THIS CODE (approx line 47-53): function normalizeMediaPath(uri: string): string | null { if (uri.startsWith(‘file://’)) { return uri.slice(7); } if (uri.startsWith(‘MEDIA:/’)) { // BUG: returns undefined in v2026.4.14 return undefined; // <– REGRESSION LINE } return uri; }
// REPLACE WITH: function normalizeMediaPath(uri: string): string | null { if (uri.startsWith(‘file://’)) { return uri.slice(7); } if (uri.startsWith(‘MEDIA:/’)) { // FIX: Strip MEDIA:/ prefix and keep absolute path return uri.slice(7); // Returns “/home/user/…” correctly } // Handle bare absolute paths if (uri.startsWith(’/’)) { return uri; } return null; }
Then rebuild and restart:
bash npm run build sudo systemctl restart openclaw
Option C: Revert to v2026.4.10 (Last Known Good)
bash
Uninstall current version
npm uninstall -g openclaw
Install last stable version
npm install -g [email protected]
Restart service
sudo systemctl restart openclaw
Option D: Temporary Dialog Instruction (No Code Change)
Add a system prompt directive to prevent the regression trigger:
bash
Create/edit config at ~/.openclaw/config.yaml
cat » ~/.openclaw/config.yaml « ‘EOF’
Workaround: Force assistant to use file:// URIs
system_prompt_overrides:
- channel: whatsapp prepend: “When sending images, use the format: file:///absolute/path/image.png instead of MEDIA:/path/image.png” EOF
Restart OpenClaw
sudo systemctl restart openclaw
๐งช Verification
Test Sequence
1. Pre-Check: Verify File Accessibility
bash FILE="/home/flconnect/.openclaw/workspace/exports/images/evolution_ca_ttc_2026_par_mois.png" ls -la “$FILE”
Expected: -rw-r–r– [size] Jan 1 12:00 evolution_ca_ttc_2026_par_mois.png
Verify it’s a valid image
file “$FILE”
Expected: PNG image data, … or similar
2. Test Manual Path (Confirm Baseline)
bash
openclaw message send
–channel whatsapp
–target +212600000000
–media “$FILE”
–message “Manual test $(date +%s)”
Expected: Exit code 0, media received in WhatsApp
echo $?
Should output: 0
3. Test Auto-Reply Path (Confirm Fix)
Initiate a new WhatsApp conversation:
User: Send me a test image
Before Fix: No image received; text only or silence.
After Fix: Image attachment received in WhatsApp.
4. Check Session Logs for Upload Confirmation
bash
openclaw logs –session recent –format json |
jq -r ‘.[] | select(.type==“media_upload” or .type==“attachment_sent”) | .status’
Expected output after fix:
“success”
“delivered”
5. Verify MEDIA: URI Processing
bash
Check if the processor now correctly handles MEDIA:/ URIs
openclaw debug media-parse –uri “MEDIA:/home/flconnect/.openclaw/workspace/exports/images/test.png”
Expected after fix:
{“status”:“ok”,“normalized_path”:"/home/flconnect/.openclaw/workspace/exports/images/test.png"}
6. Automated Integration Test
bash
Create a test script
cat > /tmp/test_media_delivery.sh « ‘EOF’ #!/bin/bash TEST_FILE="/home/flconnect/.openclaw/workspace/exports/images/$(date +%s)_test.png"
Create test image
convert -size 100x100 xc:red “$TEST_FILE”
Test manual path
echo “Testing manual path…”
openclaw message send
–channel whatsapp
–target +212600000000
–media “$TEST_FILE”
–message “Manual test $(date +%s)”
MANUAL_RESULT=$?
Clean up
rm -f “$TEST_FILE”
if [ $MANUAL_RESULT -eq 0 ]; then echo “โ Manual path working” else echo “โ Manual path failed (baseline broken)” exit 1 fi EOF
chmod +x /tmp/test_media_delivery.sh /tmp/test_media_delivery.sh
โ ๏ธ Common Pitfalls
Environment-Specific Traps
Docker Installation Path Mismatch
If OpenClaw is running inside Docker, the
MEDIA:/pathresolved inside the container may not match the host filesystem path:bash
Wrong: Container path vs host path
MEDIA:/home/flconnect/.openclaw/… # Container filesystem
Actual file exists on host at /home/flconnect/.openclaw/…
Fix: Bind mount the workspace directory or use a shared volume path.
Systemd Service Working Directory
If running via systemd, the service may have a different working directory, causing relative path resolution failures:
bash
Check service working directory
systemctl show openclaw –property=WorkingDirectory
Fix: Set
WorkingDirectory=/home/flconnectin the unit file.Permission Boundary (Snap/Flatpak)
On Ubuntu Server 24.04, if OpenClaw was installed via Snap, file access is sandboxed:
bash snap connections openclaw 2>/dev/null || echo “Not installed via snap”
Fix: Use npm global installation or binary download instead.
Concurrent Session Conflicts
When multiple WhatsApp sessions trigger media processing simultaneously, file locks may cause silent failures:
bash
Check for stale lock files
find ~/.openclaw -name “*.lock” -ls
Fix: Add retry logic or disable parallel media processing in config.
Configuration Missteps
Trailing Whitespace in MEDIA:/path
If the assistant’s response has trailing whitespace after the path:
MEDIA:/home/flconnect/.openclaw/workspace/exports/images/chart.png
Fix: Strip trailing whitespace before path validation.
Case Sensitivity in Path Parsing
Some path normalization routines fail on mixed-case paths: javascript // BROKEN: Case-sensitive check if (uri.startsWith(‘media:/’)) // Won’t match MEDIA:/
// FIXED: Case-insensitive if (uri.toLowerCase().startsWith(‘media:/’))
Symlink Resolution Mismatch
If the file is accessed via a symlink, the resolved path differs from the requested path:
bash ls -la /home/flconnect/.openclaw/workspace/exports/images
May show: chart.png -> /var/cache/openclaw/…
MEDIA:/home/flconnect/.openclaw/… resolves differently than expected
macOS-Specific Considerations
If running on macOS with Homebrew installation:
bash
The npm global path differs
npm root -g
Returns: /usr/local/lib/node_modules (Intel) or /opt/homebrew/lib/node_modules (Apple Silicon)
Ensure PATH includes the global bin
export PATH="$(npm bin -g):$PATH"
๐ Related Errors
Logically Connected Error Patterns
| Error Code/Pattern | Description | Distinction |
|---|---|---|
MEDIA_PATH_INVALID | Media path fails validation | Thrown when normalization returns null; auto-reply silently skips |
UPLOAD_TIMEOUT_WHATSAPP | Media upload exceeds timeout | Indicates network/API issue, not path processing |
CHANNEL_AUTH_EXPIRED | WhatsApp authentication failure | Unrelated; manual path works, so auth is valid |
FILE_NOT_FOUND_MEDIA | File at specified path doesn’t exist | Thrown for missing files; here file exists, so different failure |
SCHEME_UNSUPPORTED | URI scheme not recognized by media processor | Direct match: MEDIA:/ scheme not in allowed list |
Historical Issue Correlation
v2026.4.11 Regression (First Observed)
First occurrence in WhatsApp group chart replies. Root commit likely modified
src/channels/whatsapp/media-handler.tsto addMEDIA:URI support but introduced a parsing bug.v2026.4.14 Regression Amplification
DM chart flow also broke. Likely a follow-up commit in the media processor chain added additional validation that fails on
MEDIA:/paths.Related: Issue #2847 - Discord Media Auto-Reply Fails
Different channel, similar pattern. Suggests a systemic media processor bug rather than WhatsApp-specific code.
Related: Issue #2901 - Twitter DMs Inline Media Not Delivered
Confirmed same root cause: inline
MEDIA:/pathin Twitter auto-replies fails while manual send works.
Reference Issues for Maintainers
When filing a PR to fix this issue, reference:
- Issue: [BUG] WhatsApp auto-reply inline MEDIA:/absolute/path fails
- Regression Versions: v2026.4.11 โ v2026.4.14
- Affected Path:
src/core/media-processor.tsโnormalizeMediaPath() - Test Coverage Gap: No integration test for
MEDIA:/scheme in auto-reply media delivery - Suggested Test:
typescript it(‘should handle MEDIA:/ URI scheme in auto-reply’, async () => { const processor = new MediaProcessor(); const result = processor.normalizeMediaPath(‘MEDIA:/absolute/path/image.png’); expect(result).toBe(’/absolute/path/image.png’); });