Channel plugin: duplicate message delivery from harness process respawn
Description
When using a custom MCP channel plugin (Matrix in our case), messages are delivered to the session multiple times — typically 2-3 deliveries of the same event.
Root Cause
The channel harness appears to spontaneously respawn the MCP plugin process ~3 minutes into a session with no preceding error. For ~10 seconds while both the old and new PIDs are alive, both processes receive the upstream event stream and both emit notifications/claude/channel for the same incoming message.
Since any in-memory deduplication state (e.g., a Set of delivered event IDs) is per-process, the newly spawned process has no knowledge of what the old process already delivered.
Reproduction
- Configure a channel plugin MCP server (e.g., a Matrix bridge using
matrix-bot-sdk) - Start Claude Code with
--dangerously-load-development-channels server:matrix - Send a message from an external client to a room the bot is monitoring
- Observe the message arriving 2-3 times — once as an inline
<channel>tag and again as<system-reminder>notifications
Observed Behavior
Same message_id delivered through multiple paths:
- Inline channel tag (from original process)
- System-reminder (same notification, different delivery path)
- System-reminder (from duplicate spawned process — observable because in-memory state like display name aliasing may differ)
Expected Behavior
Each unique message_id from a channel plugin should be delivered exactly once to the session.
Workaround
We implemented server-side deduplication (event ID tracking + startup timestamp guard) which prevents duplicate emissions from our MCP server, but cannot prevent the harness from spawning a duplicate process that bypasses this.
Environment
- Claude Code version: latest (as of 2026-03-21)
- OS: NixOS (Linux 6.18.18)
- Channel: Custom Matrix MCP plugin using
matrix-bot-sdk+@modelcontextprotocol/sdk - Flag:
--dangerously-load-development-channels server:matrix
Possibly related to #36800.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗