[BUG] run_in_background task-notification routed to wrong session/project
What's Wrong?
A background task (launched via the Bash tool's run_in_background: true) sometimes never delivers its completion notification to the session that launched it. Instead, the <task-notification> is queued and delivered to a different, unrelated session — one that happens to be active when the task finishes, in a directory that isn't even the same project as the one the task ran in.
From the session's perspective that launched the task, it just looks like the background shell is "hung forever" — /tasks (or asking the agent to check) shows it as still running, with no way to know the notification already fired somewhere else.
What Should Happen?
Either:
- The completion notification should be delivered to (or remain visible/queryable from) the session that actually launched the task, regardless of whether that session is still the "active" one, or
- If cross-session delivery is intentional (e.g. so a new session in the same project can pick up in-flight work), it should at minimum be scoped to the same project directory the task was launched in — not delivered into a session working in a completely different, unrelated project.
Steps to Reproduce
- Start a Claude Code session in project directory A, launch a long-running command in the background (
run_in_background: true). - End that session (or let it go idle) before the command finishes.
- Start a new Claude Code session — in a different, unrelated project directory B.
- Wait for the background command from step 1 to finish.
- The
<task-notification>for the step-1 task is delivered into the new session in project B, not into the original session A (which never receives it and, if reopened, still shows the task as unresolved).
I found this by grepping my own local session transcripts (~/.claude/projects/**/*.jsonl) for a run_in_background launch whose task id never resolves in the same transcript. Concrete instance from my own logs (paths/project names redacted, mechanism preserved):
- Session A (
cwd: project X) launches a background command atT+0s; getsbackgroundTaskId: <id>. - Session A's turn ends normally ~67s later (clean stop-hook + turn_duration, not a crash) — no notification for
<id>ever appears in session A's transcript. - A different session B (unrelated
cwd: project Y, a completely different repo than project X) receives aqueue-operation: enqueueentry for<task-notification><task-id><id></task-id>...<status>completed</status>...about 6 minutes later — followed immediately by aqueue-operation: remove. - Session A never sees this. If a user doesn't happen to have another session open in exactly the right place at exactly the right time, the notification is effectively lost from their point of view.
Claude Code Version
2.1.205 (Claude Code) — issue was captured on 2.1.204, reproducible mechanism (notification queue keyed loosely, not to the launching session) appears unchanged in 2.1.205.
Is this a regression?
I don't know
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
This may be the underlying cause of a broader, frequently-reported symptom: background shells that appear to "hang" or never complete from the user's perspective, even though the underlying command finished normally (exit code 0 in the case I traced). If task-notification routing is keyed off something like "whichever session is currently active" rather than the session (or at least the project) that launched the task, that would explain reports of background tasks silently never resolving — the resolution happened, just not where the user was looking.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗