[BUG] Teammate InboxPoller marks messages as read before delivery — "Session busy" causes permanent message loss and frozen teammate

Resolved 💬 2 comments Opened Feb 12, 2026 by TioGlo Closed Mar 13, 2026

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 read until 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

  1. Create a team with 3+ teammates via TeamCreate
  2. Have teammates engage in multi-round communication (e.g., a debate with several message exchanges)
  3. Send a message to a teammate that is currently mid-turn (processing a previous message or executing tools)
  4. 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:

  1. readUnreadMessages() finds 1 unread message
  2. markMessagesAsRead() writes "read": true to the inbox JSON file — this is the point of no return
  3. InboxPoller checks if the session can accept the message — finds it "busy"
  4. Message is "queued for later delivery"
  5. The queued delivery mechanism never retries (no timer, no event, no re-check)
  6. On the next polling cycle, readUnreadMessages() finds 0 unread (because step 2 already marked it)
  7. The agent is stuck forever

The fix should be one of:

  • Don't mark messages as read until 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.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗