claude-code - 💡(How to fix) Fix Duplicate task-notification responses after TaskOutput consumption [2 comments, 2 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
anthropics/claude-code#52786Fetched 2026-04-25 06:20:59
View on GitHub
Comments
2
Participants
2
Timeline
9
Reactions
0
Timeline (top)
labeled ×5commented ×2closed ×1cross-referenced ×1

Root Cause

Race condition between enqueueShellNotification and TaskOutput's notified flag.

In LocalShellTask.tsx (lines 226-243), when a background task completes:

1. updateTaskState → status = 'completed'     (sync)
2. enqueueShellNotification → checks notified flag, enqueues notification (sync)

Steps 1 and 2 run synchronously in the same microtask. Meanwhile, TaskOutput's waitForTaskCompletion (TaskOutputTool.tsx:122-137) polls every 100ms. By the time it detects the status change and marks notified: true (line 272-275), the notification has already been enqueued in step 2.

The notified flag only prevents duplicate enqueue — it does not remove notifications that are already in the queue.

Additionally, these notifications have priority: 'later' (LocalShellTask.tsx:169), so they are not consumed by the mid-turn drain in query.ts:1570-1571 (which only drains 'next' priority unless a Sleep tool was used). They sit in the queue until the turn ends, at which point useQueueProcessor dequeues them and triggers new model response turns.

Code Example

Run 5 commands in the background simultaneously: each sleeps 3 seconds then outputs 1 through 5. Wait for all to complete and tell me the results.

---

1. updateTaskState → status = 'completed'     (sync)
2. enqueueShellNotification → checks notified flag, enqueues notification (sync)
RAW_BUFFERClick to expand / collapse

Bug Description

When background bash tasks are consumed via TaskOutput(block: true), the task-notification messages still remain in the command queue and trigger redundant model response turns after the main turn completes.

Reproduction

Prompt:

Run 5 commands in the background simultaneously: each sleeps 3 seconds then outputs 1 through 5. Wait for all to complete and tell me the results.

Expected Behavior

The model uses TaskOutput(block: true) to wait for all 5 tasks, summarizes the results in one response, and the conversation ends cleanly.

Actual Behavior

After the model's summary response, 5 stale task-notification messages are dequeued one by one, triggering an additional redundant model turn that says something like "All 5 background commands confirmed complete" — repeating what was already said.

Root Cause

Race condition between enqueueShellNotification and TaskOutput's notified flag.

In LocalShellTask.tsx (lines 226-243), when a background task completes:

1. updateTaskState → status = 'completed'     (sync)
2. enqueueShellNotification → checks notified flag, enqueues notification (sync)

Steps 1 and 2 run synchronously in the same microtask. Meanwhile, TaskOutput's waitForTaskCompletion (TaskOutputTool.tsx:122-137) polls every 100ms. By the time it detects the status change and marks notified: true (line 272-275), the notification has already been enqueued in step 2.

The notified flag only prevents duplicate enqueue — it does not remove notifications that are already in the queue.

Additionally, these notifications have priority: 'later' (LocalShellTask.tsx:169), so they are not consumed by the mid-turn drain in query.ts:1570-1571 (which only drains 'next' priority unless a Sleep tool was used). They sit in the queue until the turn ends, at which point useQueueProcessor dequeues them and triggers new model response turns.

Impact

  • Redundant model turns with no useful content ("Already processed, no action needed")
  • Wasted tokens (~50K+ cache read input tokens per redundant turn)
  • Confusing UX — the model appears to talk to itself after completing the task
  • Scales linearly with the number of background tasks (N tasks = N redundant notifications)

Suggested Fix

A few possible approaches:

  1. Remove consumed notifications from queue: When TaskOutput successfully retrieves a task result, also remove any matching task-notification from the command queue by task ID.
  2. Filter at dequeue time: In processQueueIfReady or useQueueProcessor, check the task's notified state and whether the notification was already consumed via TaskOutput before sending it to the model.
  3. Promote priority: Change background bash task notifications from 'later' to 'next' so they get consumed by the mid-turn drain in the same turn as TaskOutput, avoiding the post-turn dequeue path entirely.

Environment

  • Claude Code version: 2.1.119
  • Model: claude-sonnet-4-6
  • OS: macOS Darwin 24.5.0

extent analysis

TL;DR

Remove or filter redundant task-notification messages from the command queue to prevent triggering unnecessary model turns after TaskOutput completes.

Guidance

  • Investigate implementing one of the suggested fixes: removing consumed notifications, filtering at dequeue time, or promoting notification priority to 'next'.
  • Verify the chosen approach by testing with multiple background tasks and checking for redundant model turns.
  • Consider the trade-offs between each fix, such as the complexity of queue manipulation versus the potential performance impact of priority changes.
  • Review the LocalShellTask.tsx and TaskOutputTool.tsx files to understand the current implementation and identify the best integration point for the chosen fix.

Example

No code snippet is provided due to the complexity of the issue and the need for a more in-depth analysis of the codebase.

Notes

The suggested fixes may have varying degrees of complexity and potential side effects, so careful testing and evaluation are necessary to determine the best approach.

Recommendation

Apply a workaround by filtering at dequeue time, as this approach may be less invasive and easier to implement than removing consumed notifications or promoting priority, and it directly addresses the issue of redundant model turns.

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