Skip to content

Background task notifications race with pending user questions, causing self-approval and unauthorized actions #36690

Closed as not planned

Description

@Benjamin-Sterrett

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:

  1. Multiple background tasks are running (run_in_background: true on Bash, or background Agents)
  2. The model asks the user a question OR completes its main work
  3. 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

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:

  1. New message role (e.g., role: notification) that the model is trained to process silently
  2. Notification coalescing — batch notifications and deliver them as context on the next actual user message, not as standalone turns
  3. Pending-question gate — if the model's last output was a question to the user, hold notifications until the user responds
  4. disableBackgroundTaskNotifications setting ([FEATURE] Add setting to disable automatic background task completion notifications #18544, closed as stale) — let users opt out of notification injection while keeping background tasks functional

Related issues

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.

Activity

  1. github-actions commented on Mar 20, 2026

    @github-actions

    Found 3 possible duplicate issues:

    1. [BUG] Background task notification causes model to self-approve pending yes/no question #34637
    2. Spurious user message injected after background task completion, triggered unauthorized production action #36540
    3. [BUG] Bug Report: Claude Code Fabricates User Input When Background Task Notifications Arrive #35725

    This issue will be automatically closed as a duplicate in 3 days.

    • If your issue is a duplicate, please close it and 👍 the existing issue instead
    • To prevent auto-closure, add a comment or 👎 this comment

    🤖 Generated with Claude Code

  2. yurishevtsov commented on Mar 23, 2026

    @yurishevtsov

    Additional data point from #37602 (same root cause, different metadata):

    Three background Bash tasks completed simultaneously while the session was idle. The model generated an assistant message impersonating the user:

    "yeah nuke it. and also I know there's also a bunch of old nvm versions I don't need..."

    Key difference from #27805: the phantom message has output_tokens: 60 (matching the actual token count), compared to #27805's anomalous output_tokens: 1. This confirms the bug can occur through normal token-by-token inference, not just the anomalous code path documented in #27805.

    input_tokens: 3 (new), cache_read: 72,634, output_tokens: 60
    model: claude-opus-4-6, stop_reason: end_turn
    message id: msg_01HpBJVv7F7LzPSoEwXAoMEh
    

    Environment: v2.1.81, Opus 4.6 (1M), macOS, --dangerously-skip-permissions, 22 active plugins, multiple hooks on UserPromptSubmit/PreToolUse/PostToolUse.

    Full JSONL evidence and timeline in #37602.

  3. msmobileapps commented on Mar 29, 2026

    @msmobileapps

    This is exactly the kind of problem that a formal supervision layer would prevent. We hit this same issue running 30+ autonomous Claude Code plugins in production.

    Our solution: every plugin declares an impact level (low/medium/high). High-impact actions (sending messages, modifying external data) are always gated behind explicit human approval — regardless of what the model's internal state looks like. The approval gate is structural, not prompt-based, so race conditions like this can't bypass it.

    This is part of SOSA (Supervised Orchestrated Secured Agents) — we open-sourced the methodology and a plugin marketplace with 30+ SOSA-compliant plugins.

    Full proposal for native adoption in #40498.

  4. github-actions commented on Apr 29, 2026

    @github-actions

    Closing for now — inactive for too long. Please open a new issue if this is still relevant.

  5. github-actions commented on May 8, 2026

    @github-actions

    This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.

  6. locked as resolved and limited conversation to collaborators on May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions