[BUG] Teammate InboxPoller marks messages as read before delivery — "Session busy" causes permanent message loss and frozen teammate
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
When a teammate receives a message while its session is "busy" (mid-API-call or mid-tool-execution), the InboxPoller marks the message as read in the inbox JSON file but fails to deliver it to the conversation. The message is "queued for later delivery" but the retry mechanism never fires. The teammate then polls forever finding 0 unread messages and becomes permanently frozen.
This is distinct from #24108 (mailbox never polled) which was fixed in v2.1.33. In this bug, polling works correctly — the issue is in the delivery pipeline after polling.
What Should Happen?
Messages delivered to a teammate's inbox should be delivered to the conversation regardless of whether the session was busy at the time of polling. Either:
- Messages should not be marked as
readuntil successfully delivered, OR - The "queued for later delivery" mechanism should reliably retry
Error Messages/Logs
From `~/.claude/debug/<session-id>.txt` for the frozen teammate:
**Message arrives and is marked read:**
21:19:21.811Z [TeammateMailbox] readUnreadMessages: 1 unread of 4 total
21:19:21.811Z [InboxPoller] Found 1 unread message(s)
21:19:21.812Z [TeammateMailbox] markMessagesAsRead: WROTE 1 message(s) as read
21:19:21.812Z [TeammateMailbox] markMessagesAsRead: VERIFY - 0 still unread after write
**Delivery fails — session is busy:**
21:19:21.812Z [InboxPoller] Session busy, queuing for later delivery
**Infinite polling loop begins (never exits):**
21:19:22.813Z [TeammateMailbox] readUnreadMessages: 0 unread of 4 total
21:19:23.814Z [TeammateMailbox] readUnreadMessages: 0 unread of 4 total
21:19:24.816Z [TeammateMailbox] readUnreadMessages: 0 unread of 4 total
... (continues every ~1s for 4+ minutes until manually killed)
21:23:52.194Z [TeammateMailbox] readUnreadMessages: 0 unread of 4 total
21:23:52.215Z [SessionEnd]
Steps to Reproduce
- Create a team with 3+ teammates via
TeamCreate - Have teammates engage in multi-round communication (e.g., a debate with several message exchanges)
- Send a message to a teammate that is currently mid-turn (processing a previous message or executing tools)
- The teammate will freeze — it reads the inbox, finds 0 unread, and loops forever
This is intermittent and depends on timing — the message must arrive while the session is "busy."
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.39
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Other
Additional Information
Root Cause Analysis
The bug is a race condition in the InboxPoller:
readUnreadMessages()finds 1 unread messagemarkMessagesAsRead()writes"read": trueto the inbox JSON file — this is the point of no return- InboxPoller checks if the session can accept the message — finds it "busy"
- Message is "queued for later delivery"
- The queued delivery mechanism never retries (no timer, no event, no re-check)
- On the next polling cycle,
readUnreadMessages()finds 0 unread (because step 2 already marked it) - The agent is stuck forever
The fix should be one of:
- Don't mark messages as
readuntil they are successfully delivered to the conversation - Implement a reliable retry mechanism for queued messages (e.g., re-check queued messages on each polling cycle)
- Use a separate "delivered" flag distinct from "read"
Impact
This affects any multi-round teammate communication pattern where messages may arrive while a teammate is mid-turn. We observed it in 2 out of 3 teams during a single session:
- A reviewer teammate that froze while other teammates were implementing
- A debate participant that froze after receiving counterarguments
The workaround is to kill the frozen tmux pane and either respawn the teammate (losing context) or have the team lead take over the frozen teammate's task.
Related Issues
- #24108 — Different bug (mailbox polling never started), fixed in v2.1.33
- #20860 — Similar symptom (messages swallowed) but in main session, not teammate inbox
Author Note
Bug report written by claude.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗