openclaw - ✅(Solved) Fix TTS tool audio blocked by normalizeReplyMediaPaths when sandbox mode is off (regression since v2026.3.22) [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#64533Fetched 2026-04-11 06:14:32
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
referenced ×2cross-referenced ×1

The built-in tts tool generates audio files at /tmp/openclaw/tts-*/voice-*.mp3. When sandbox mode is "off" (default), these files are silently dropped by normalizeReplyMediaPaths because isAllowedAbsoluteReplyMediaPath does not permit /tmp/openclaw/ paths in the non-sandboxed code path.

This is a regression introduced in v2026.3.22 (commit 3cd4978fc2 — "refactor(agents): unify tool media reply delivery"). TTS tool audio delivery works on v2026.3.7 but breaks on v2026.3.22+.

Root Cause

In isAllowedAbsoluteReplyMediaPath, the function resolveAllowedTmpMediaPath (which correctly allows /tmp/openclaw/*) is only called inside the if (sandboxRoot) branch. When sandbox mode is "off", sandboxRoot is undefined and this check is never reached.

Since /tmp/openclaw/* files are always created by OpenClaw itself (via resolvePreferredOpenClawTmpDir() for TTS, image generation, etc.), they should be allowed regardless of sandbox mode.

Fix Action

Workaround

Patch agent-runner.runtime-*.js manually after each OpenClaw install:

sed -i 's/function isAllowedAbsoluteReplyMediaPath(params) {/function isAllowedAbsoluteReplyMediaPath(params) {\n\tif (params.candidate.startsWith("\/tmp\/openclaw\/")) return true;/' \
  /usr/lib/node_modules/openclaw/dist/agent-runner.runtime-*.js

Note: This patch is overwritten by every npm install -g openclaw@latest.

PR fix notes

PR #64539: fix(reply): allow OpenClaw tmp media in normalizer

Description (problem / solution / changelog)

Summary

  • allow reply media normalization to keep OpenClaw-managed temp files under the preferred tmp root even when sandbox mode is off
  • preserve the existing host-path restrictions by only allowing the managed OpenClaw tmp directory, not arbitrary /tmp paths
  • add focused regression tests covering sandbox.mode=off for both allowed /tmp/openclaw media and blocked unrelated absolute host-local media

Closes #64533

Testing

  • attempted: OPENCLAW_LOCAL_CHECK=0 pnpm test src/auto-reply/reply/reply-media-paths.test.ts
  • blocked locally because this worktree does not have node_modules / vitest installed
  • attempted pnpm install, but dependency installation was blocked by transient registry/network resolution in this environment
  • sending to CI for verification

Changed files

  • src/auto-reply/reply/reply-media-paths.test.ts (modified, +71/-1)
  • src/auto-reply/reply/reply-media-paths.ts (modified, +29/-1)

Code Example

function isAllowedAbsoluteReplyMediaPath(params) {
    // OpenClaw's own temp files should always be allowed
    if (params.candidate.startsWith("/tmp/openclaw/")) return true;
    if (isManagedGlobalReplyMediaPath(params.candidate)) return true;
    // ... existing sandbox checks
}

---

sed -i 's/function isAllowedAbsoluteReplyMediaPath(params) {/function isAllowedAbsoluteReplyMediaPath(params) {\n\tif (params.candidate.startsWith("\/tmp\/openclaw\/")) return true;/' \
  /usr/lib/node_modules/openclaw/dist/agent-runner.runtime-*.js
RAW_BUFFERClick to expand / collapse

TTS tool audio blocked by normalizeReplyMediaPaths when sandbox mode is "off"

Description

The built-in tts tool generates audio files at /tmp/openclaw/tts-*/voice-*.mp3. When sandbox mode is "off" (default), these files are silently dropped by normalizeReplyMediaPaths because isAllowedAbsoluteReplyMediaPath does not permit /tmp/openclaw/ paths in the non-sandboxed code path.

This is a regression introduced in v2026.3.22 (commit 3cd4978fc2 — "refactor(agents): unify tool media reply delivery"). TTS tool audio delivery works on v2026.3.7 but breaks on v2026.3.22+.

Regression timeline

  • v2026.3.7 and earlier: Tool results used inline MEDIA: directives, bypassing normalizeReplyMediaPaths. TTS worked.
  • v2026.3.22: Commit 3cd4978fc2 unified tool media delivery to use structured details.media.mediaUrl, which now routes through createReplyMediaPathNormalizer(). /tmp/openclaw/ paths hit isAllowedAbsoluteReplyMediaPath for the first time and get blocked.
  • v2026.3.24: Further tightened in commit c92002e1 ("fix(media): align outbound media access with fs policy").
  • v2026.4.7: Partial fix re-allowed managed MEDIA: paths but did NOT add /tmp/openclaw/ to the allowlist.
  • v2026.4.9: Still broken.

Related PRs

  • PR #63511: "fix(tts): allow OpenClaw temp directory paths in reply media normalizer"
  • PR #63932: "fix: allow TTS tool media delivery to channels"

Steps to reproduce

  1. Set sandbox.mode: "off" (default)
  2. Do NOT configure messages.tts (leave empty — TTS tool is always available)
  3. Send a message like "Say hello as a voice message"
  4. Agent calls the tts tool, generates /tmp/openclaw/tts-*/voice-*.mp3
  5. Audio file is created but never delivered to the channel

Expected behavior

The TTS audio should be delivered to the channel via emitBlockReplyblockReplyHandler → channel's deliver callback, regardless of sandbox mode.

Actual behavior

normalizeReplyMediaPaths in agent-runner.runtime calls isAllowedAbsoluteReplyMediaPath, which:

  1. Checks isManagedGlobalReplyMediaPath → false (/tmp/openclaw/ is not under ~/.openclaw/media/)
  2. Checks workspace/sandbox roots → false (sandbox is off, no sandboxRoot)
  3. Throws "Absolute host-local MEDIA paths are blocked in normal replies."
  4. Catch handler silently drops the media: logVerbose("dropping blocked reply media...")
  5. Payload arrives at the channel with mediaUrl: undefined — audio lost

Root cause

In isAllowedAbsoluteReplyMediaPath, the function resolveAllowedTmpMediaPath (which correctly allows /tmp/openclaw/*) is only called inside the if (sandboxRoot) branch. When sandbox mode is "off", sandboxRoot is undefined and this check is never reached.

Since /tmp/openclaw/* files are always created by OpenClaw itself (via resolvePreferredOpenClawTmpDir() for TTS, image generation, etc.), they should be allowed regardless of sandbox mode.

Suggested fix

In isAllowedAbsoluteReplyMediaPath, add the /tmp/openclaw/ check before the sandbox-specific checks:

function isAllowedAbsoluteReplyMediaPath(params) {
    // OpenClaw's own temp files should always be allowed
    if (params.candidate.startsWith("/tmp/openclaw/")) return true;
    if (isManagedGlobalReplyMediaPath(params.candidate)) return true;
    // ... existing sandbox checks
}

Or more robustly, call resolveAllowedTmpMediaPath() regardless of sandbox mode.

Workaround

Patch agent-runner.runtime-*.js manually after each OpenClaw install:

sed -i 's/function isAllowedAbsoluteReplyMediaPath(params) {/function isAllowedAbsoluteReplyMediaPath(params) {\n\tif (params.candidate.startsWith("\/tmp\/openclaw\/")) return true;/' \
  /usr/lib/node_modules/openclaw/dist/agent-runner.runtime-*.js

Note: This patch is overwritten by every npm install -g openclaw@latest.

Environment

  • OpenClaw v2026.4.9 (broken)
  • OpenClaw v2026.3.7 (works)
  • Regression introduced: v2026.3.22
  • sandbox.mode: "off" (default)
  • TTS provider: ElevenLabs and edge (both affected)
  • Tested on custom channel plugin, but affects all channels

extent analysis

TL;DR

The most likely fix for the TTS tool audio being blocked is to modify the isAllowedAbsoluteReplyMediaPath function to allow /tmp/openclaw/ paths regardless of sandbox mode.

Guidance

  • Modify the isAllowedAbsoluteReplyMediaPath function to include a check for /tmp/openclaw/ paths before the sandbox-specific checks.
  • Consider calling resolveAllowedTmpMediaPath() regardless of sandbox mode for a more robust solution.
  • As a temporary workaround, manually patch the agent-runner.runtime-*.js file after each OpenClaw install to add the necessary check.
  • Verify the fix by testing the TTS tool with sandbox mode set to "off" and checking if the audio is delivered to the channel.

Example

function isAllowedAbsoluteReplyMediaPath(params) {
    // OpenClaw's own temp files should always be allowed
    if (params.candidate.startsWith("/tmp/openclaw/")) return true;
    if (isManagedGlobalReplyMediaPath(params.candidate)) return true;
    // ... existing sandbox checks
}

Notes

The provided fix is specific to the isAllowedAbsoluteReplyMediaPath function and may not address other potential issues. Additionally, the manual patch workaround will be overwritten by every npm install -g openclaw@latest, so a more permanent solution is recommended.

Recommendation

Apply the suggested fix to the isAllowedAbsoluteReplyMediaPath function to allow /tmp/openclaw/ paths regardless of sandbox mode, as this is a more robust and permanent solution compared to the manual patch workaround.

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…

FAQ

Expected behavior

The TTS audio should be delivered to the channel via emitBlockReplyblockReplyHandler → channel's deliver callback, regardless of sandbox mode.

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 - ✅(Solved) Fix TTS tool audio blocked by normalizeReplyMediaPaths when sandbox mode is off (regression since v2026.3.22) [1 pull requests, 1 participants]