Skip to content

[Bug]: iMessage remote attachment staged after media understanding — image tool sees raw Mac path before SCP fetch #87089

Description

@dwonshin

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions