openclaw - 💡(How to fix) Fix iMessage echo loop: is_from_me messages not filtered correctly, bot responds to its own sent messages [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#63386Fetched 2026-04-09 07:54:28
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0

The iMessage channel enters an infinite echo loop where the bot processes its own sent messages as incoming messages and responds to them repeatedly.

Error Message

  • Bot sends repeated error messages to the user

Root Cause

Root Cause (investigated)

Fix Action

Workaround

Manually delete the sent loop messages from ~/Library/Messages/chat.db and keep the iMessage channel disabled until a fix is released.

Code Example

subscriptionId = (await client.request("watch.subscribe", { attachments: includeAttachments }))?.subscription ?? null;
RAW_BUFFERClick to expand / collapse

Summary

The iMessage channel enters an infinite echo loop where the bot processes its own sent messages as incoming messages and responds to them repeatedly.

Environment

  • OpenClaw: 2026.3.31 (also reproduced on 2026.4.8)
  • imsg: 0.5.0 (steipete/tap)
  • macOS: 15.x (Darwin 25.4.0)
  • Model: google/gemini-2.5-flash
  • Channel config: dmPolicy: allowlist, allowFrom: ["+420XXXXXXXXX"]

Steps to Reproduce

  1. Start OpenClaw gateway with iMessage channel enabled
  2. Send a message to the bot from an allowlisted number
  3. Bot responds correctly on the first message
  4. Bot immediately starts sending repeated replies to itself

The loop is especially severe after a gateway restart: imsg replays recent messages from chat.db (including sent ones) and the echo filter fails to suppress them.

Root Cause (investigated)

Two compounding issues found in monitor-provider-SidE3uPF.js:

1. No --since-rowid persistence across restarts

watch.subscribe is called without a since-rowid parameter:

subscriptionId = (await client.request("watch.subscribe", { attachments: includeAttachments }))?.subscription ?? null;

On every gateway restart, imsg replays all recent messages from chat.db including is_from_me: true sent messages. There is no persistent cursor stored to disk.

2. In-memory echo cache with very short TTL

The DefaultSentMessageCache that backs is_from_me echo detection is purely in-memory with TTLs of 4s (text) and 60s (message ID). After a restart the cache is empty, so previously sent messages are no longer recognized as echoes and are processed as new incoming messages.

The is_from_me direct-drop path (return { kind: "drop", reason: "from me" }) appears to not fire reliably in practice for non-self-chat DMs, allowing sent messages to reach the agent.

Impact

  • Infinite loop of API calls → Google Gemini 503 rate limit errors
  • Bot sends repeated error messages to the user
  • Loop persists across gateway restarts until messages are manually deleted from chat.db

Expected Behavior

Sent messages (is_from_me: true) should never trigger an agent run. watch.subscribe should persist the last processed rowid to disk and restore it on startup so replayed messages are not reprocessed.

Workaround

Manually delete the sent loop messages from ~/Library/Messages/chat.db and keep the iMessage channel disabled until a fix is released.

extent analysis

TL;DR

Implementing persistence for the since-rowid parameter in watch.subscribe and improving the DefaultSentMessageCache to prevent echo loops are likely fixes.

Guidance

  • Modify the watch.subscribe call to include a since-rowid parameter that is persisted across restarts, such as storing the last processed rowid in a file or database.
  • Increase the TTL of the DefaultSentMessageCache or implement a more robust caching mechanism to prevent sent messages from being reprocessed after a restart.
  • Consider adding a reliable is_from_me direct-drop path to prevent sent messages from reaching the agent.
  • Verify that the is_from_me detection is working correctly for non-self-chat DMs.

Example

// Example of persisting the last processed rowid
const fs = require('fs');
const lastRowidFile = 'last_rowid.txt';

// Load the last processed rowid from file
let lastRowid;
try {
  lastRowid = fs.readFileSync(lastRowidFile, 'utf8');
} catch (err) {
  lastRowid = null;
}

// Subscribe with the last processed rowid
subscriptionId = (await client.request("watch.subscribe", { 
  attachments: includeAttachments, 
  sinceRowid: lastRowid 
}))?.subscription ?? null;

// Store the new last processed rowid
fs.writeFileSync(lastRowidFile, subscriptionId);

Notes

The provided example is a basic illustration and may need to be adapted to the specific requirements of the application. The DefaultSentMessageCache implementation and the is_from_me detection logic may also require modifications to ensure reliable echo loop prevention.

Recommendation

Apply a workaround by manually deleting the sent loop messages from ~/Library/Messages/chat.db and keeping the iMessage channel disabled until a fix is released, as the root cause issues are related to the persistence of the since-rowid parameter and the caching mechanism.

FAIL-SAFE

If the issue lacks enough information, a minimal TL;DR would be "Implementing persistence for the since-rowid parameter and improving the caching mechanism may prevent echo loops." with a single guidance point to review the watch.subscribe call and caching implementation.

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…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING