Skip to content

iMessage self-chat echo: reflected duplicate messages bypass from-me filtering #32166

Description

@tomroberts78

Summary

When OpenClaw's iMessage channel is used in a self-chat scenario (owner messaging their own iMessage address), every message creates two entries in the Messages database with different is_from_me values but identical text and timestamps. The existing is_from_me:true filter drops one copy, but the is_from_me:false duplicate passes through and gets processed as a new inbound message — creating an echo loop.

Reproduction

  1. Configure the iMessage channel with imsg CLI
  2. Send a message to yourself (e.g. from your iPhone to the same iCloud address the Mac is signed into)
  3. The agent receives the message, replies
  4. The reply generates two database entries:
    • is_from_me:true (correctly dropped by the handler at reply-XaR8IPbY.js:40925)
    • is_from_me:false (passes through as a new inbound message → echo)
  5. This creates infinite echo loops

Evidence from imsg rpc debug log

Same message, 2 seconds apart, different GUIDs, different is_from_me:

// is_from_me:true — correctly dropped
{"params":{"message":{"id":9641,"is_from_me":true,"text":"Do you want to report this issue?","created_at":"2026-03-02T20:58:10.649Z","guid":"0126C9E6-..."}},"method":"message"}

// is_from_me:false — echo duplicate, NOT dropped
{"params":{"message":{"id":9642,"is_from_me":false,"text":"Do you want to report this issue?","created_at":"2026-03-02T20:58:10.649Z","guid":"35C54324-..."}},"method":"message"}

Suggested fix

For self-chat detection, when both sender and destination_caller_id are the same address AND an is_from_me:true message was recently seen with the same text + created_at, drop the is_from_me:false duplicate.

Alternatively, track recently sent message GUIDs or text hashes and dedup within a short time window.

Also affects BlueBubbles channel

The BlueBubbles channel has the same issue — the webhook fires for both sent and received copies of self-chat messages.

Additional bug: Control UI blocks webhook POST requests

While debugging this, we discovered that handleControlUiHttpRequest() in the gateway rejects ALL non-GET/HEAD HTTP requests with 405 before checking the request path. This blocks webhook delivery for any webhook-based channel (BlueBubbles, potentially Telegram, Google Chat) when the Control UI is enabled.

The method check at the top of the function should be moved after the basePath / pathname matching, so only Control UI paths reject POST.

Environment

  • OpenClaw: latest (npm, 2026-03-02)
  • macOS: Tahoe 26.3.0 (arm64)
  • imsg: 0.5.0
  • BlueBubbles: 1.9.9

Metadata

Metadata

Assignees

Labels

dedupe:parentPrimary canonical item in dedupe cluster

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions