Environment
- OpenClaw version: 2026.5.22
- Gateway host: Linux (Ubuntu)
- iMessage host: remote Mac via SSH/SCP (
channels.imessage.remoteHost set)
- iMessage bridge:
imsg (native OpenClaw iMessage channel)
Config (relevant excerpt)
{
"channels": {
"imessage": {
"enabled": true,
"cliPath": "/path/to/imsg-ssh",
"remoteHost": "kaien@nerv",
"dbPath": "/Users/kaien/Library/Messages/chat.db",
"includeAttachments": true,
"remoteAttachmentRoots": ["/Users/*/Library/Messages/Attachments"],
"attachmentRoots": ["/Users/*/Library/Messages/Attachments"]
}
}
}
What happened
When a user sends an iMessage photo attachment, the agent cannot analyze it. The image tool fails with:
Local media path is not under an allowed directory: /Users/kaien/Library/Messages/Attachments/.../IMG_0351.jpeg
Root cause
The iMessage monitor intentionally skips local staging when remoteHost is set (correct behavior):
// monitor-CPg00T5t.js
const stagedAttachments = remoteHost ? [] : await stageIMessageAttachments(validAttachments, {...});
const mediaAttachments = remoteHost ? rawMediaAttachments : stagedAttachments;
It passes the raw Mac path (/Users/kaien/...) and sets MediaRemoteHost in the inbound context, expecting stageSandboxMedia to SCP-fetch the file and rewrite the path before media understanding runs.
However, in get-reply-DOTqK3jN.js, the pipeline order is:
1. applyMediaUnderstandingIfNeeded(...) ← sees raw Mac path → fails
2. stageSandboxMedia(...) ← too late
3. runPreparedInboundReplyTurn(...)
stageSandboxMedia is called after applyMediaUnderstandingIfNeeded, so the image tool sees the unreachable Mac path before SCP staging has a chance to rewrite it to a local cache path.
Expected behavior
1. stageSandboxMedia(...) ← SCP fetch, rewrite path to /home/.../.openclaw/media/remote-cache/...
2. applyMediaUnderstandingIfNeeded(...) ← sees local cached path → succeeds
3. runPreparedInboundReplyTurn(...)
Workaround applied
Patched get-reply-DOTqK3jN.js directly to call stageSandboxMedia before applyMediaUnderstandingIfNeeded when MediaRemoteHost is set and media has not yet been staged:
if (!useFastTestBootstrap && agentSessionKey && !finalized.MediaStaged && hasInboundMedia(finalized)) {
const { stageSandboxMedia } = await loadStageSandboxMediaRuntime();
await traceGetReplyPhase("reply.stage_media_pre_understanding", () => stageSandboxMedia({
ctx: finalized,
sessionCtx: finalized,
cfg,
sessionKey: agentSessionKey,
workspaceDir
}));
}
After applying this patch and restarting the gateway, iMessage photo attachments are correctly SCP-fetched and analyzed.
Notes
Environment
channels.imessage.remoteHostset)imsg(native OpenClaw iMessage channel)Config (relevant excerpt)
{ "channels": { "imessage": { "enabled": true, "cliPath": "/path/to/imsg-ssh", "remoteHost": "kaien@nerv", "dbPath": "/Users/kaien/Library/Messages/chat.db", "includeAttachments": true, "remoteAttachmentRoots": ["/Users/*/Library/Messages/Attachments"], "attachmentRoots": ["/Users/*/Library/Messages/Attachments"] } } }What happened
When a user sends an iMessage photo attachment, the agent cannot analyze it. The image tool fails with:
Root cause
The iMessage monitor intentionally skips local staging when
remoteHostis set (correct behavior):It passes the raw Mac path (
/Users/kaien/...) and setsMediaRemoteHostin the inbound context, expectingstageSandboxMediato SCP-fetch the file and rewrite the path before media understanding runs.However, in
get-reply-DOTqK3jN.js, the pipeline order is:stageSandboxMediais called afterapplyMediaUnderstandingIfNeeded, so the image tool sees the unreachable Mac path before SCP staging has a chance to rewrite it to a local cache path.Expected behavior
Workaround applied
Patched
get-reply-DOTqK3jN.jsdirectly to callstageSandboxMediabeforeapplyMediaUnderstandingIfNeededwhenMediaRemoteHostis set and media has not yet been staged:After applying this patch and restarting the gateway, iMessage photo attachments are correctly SCP-fetched and analyzed.
Notes
remoteHostis not set and the local staging path works correctly.stage-sandbox-media-Cvwi-a_Q.js) and all related config options (remoteHost,remoteAttachmentRoots) are already correct — this is purely a pipeline ordering issue.attachmentRootsnot being threaded into the image tool'slocalRoots; this bug is about staging order for remote hosts)