Background task notifications race with pending user questions, causing self-approval and unauthorized actions
Summary
Background task completion notifications are injected into the conversation as role: user messages. When the model has asked the user a question and is waiting for a response, these notifications get interpreted as conversational input — causing the model to either self-approve pending questions, fabricate plausible user responses, or generate unnecessary output after work is complete.
I've been experiencing this consistently for ~2 months across multiple projects. It happens reliably during long autonomous sessions with parallel background work (reviews, scans, agents).
Two failure modes
1. Self-approval of pending questions
The model asks a yes/no question ("Want me to proceed?"), a background task completes, and the model treats the notification as a green light to continue — before the user has responded.
Example: Model completed a root cause investigation, asked "Want me to proceed with the fix via dev-workflow?", then two background Bash commands (Vercel log checks) completed. The model immediately invoked the dev-workflow skill, wrote state files, and started creating tasks — all before my "yes" came through. If I'd said "no" or "try a different approach," it would have been halfway through the wrong thing.
2. Unnecessary output after completed work
The model finishes a task and outputs its summary ("Done. Here's what changed..."). Background tasks (parallel reviews, scans) complete minutes later. The model generates additional responses to each notification, producing noise like "All background tasks completed. The workflow is done." This output adds nothing — the work was already done.
Example: A 24-minute autonomous workflow completed (branch created, PR merged, Linear updated). Five background tasks then completed one by one (Semgrep scan, security review agent, Codex review x2, Codex PR review). The model responded to the batch: "All background tasks completed. The workflow is done — PR #17 merged, PRJ-310 closed, hook is live." This was already stated in the completion summary minutes earlier.
Reproduction
This reproduces reliably when:
- Multiple background tasks are running (
run_in_background: trueon Bash, or background Agents) - The model asks the user a question OR completes its main work
- Background tasks complete after step 2, injecting
<task-notification>blocks
The more background tasks running in parallel, the more likely this is to trigger. My typical workflow runs 3-5 parallel background tasks (SAST scanning, code review, security review agents, PR review), which makes this nearly guaranteed per session.
Environment
- Claude Code v2.1.80
- macOS (Darwin 25.3.0, M4 Mac Mini)
- Claude Max subscription
- Model: claude-opus-4-6 (1M context)
Root cause
Background task completion notifications are delivered as role: user messages because the Chat Completions API has no alternative message role for system/agent events. The model cannot reliably distinguish these from actual user input.
This is architectural — not a prompt engineering problem. I've had instructions in my CLAUDE.md for months telling the model to produce zero output on <task-notification> blocks, and it helps but doesn't reliably prevent the behavior.
Impact
- Safety: The model can self-approve destructive actions (file deletion, production deploys, force pushes) by treating a notification as user confirmation. Issues #36540, #34637, and #34439 document cases where this led to unauthorized production actions, 2.9 GB of deleted files, and fabricated user responses.
- Trust: Users learn they can't step away during background work because the model might act on its own. This undermines the value proposition of background/parallel tasks.
- Token waste: Every notification forces a model response, consuming tokens for zero-value output.
Workaround attempts
| Approach | Result |
|----------|--------|
| CLAUDE.md instruction: "task notifications produce ZERO output" | Partially works, not reliable |
| CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 | Works but kills all parallelism |
| Memory/feedback instructions about pending questions | Too new to evaluate |
| PreToolUse hooks | Can't intercept — notifications bypass hook pipeline (#18544) |
Suggested fix
The notification system needs a way to deliver background task results to the model without triggering a new conversational turn. Options:
- New message role (e.g.,
role: notification) that the model is trained to process silently - Notification coalescing — batch notifications and deliver them as context on the next actual user message, not as standalone turns
- Pending-question gate — if the model's last output was a question to the user, hold notifications until the user responds
disableBackgroundTaskNotificationssetting (#18544, closed as stale) — let users opt out of notification injection while keeping background tasks functional
Related issues
- #36540 — Fabricated user message triggered unauthorized production deploy
- #34637 — Self-approved file deletion (2.9 GB)
- #34439 — Fabricated user response, modified 30 configs
- #27805 — Hallucinated user message with anomalous API metadata
- #35610 — Background agent notifications mistaken for user messages
- #35725 — Fabricated dialogue during pip installs
- #33872 — Microtask/macrotask race condition in notification delivery
- #32029 — Auto-compact prompt causes self-approval
- #21700 — Task notification context confusion
- #18544 — Feature request for notification suppression (closed as stale)
- #17456 — Notifications force unnecessary model responses
- #10628 — Earliest report (Oct 2025) — hallucinated
###Human:mid-response
This issue has been reported in various forms since October 2025 with no official acknowledgment. As autonomous/agentic workflows with parallel background tasks become the primary usage pattern for Claude Code, this will affect an increasing number of users.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗