claude-code - 💡(How to fix) Fix Stop hook trace `No stderr output` fires every turn for passing hooks (session-scoped)

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…

In a single long-running session, the Stop hook trace [<command>]: No stderr output started displaying after every assistant turn — for ~30+ consecutive turns — despite the hook passing cleanly (exit 0, no stderr, no block). The same hook configuration in other sessions does not produce this trace. Once the noise starts in a session, it persists.

Error Message

  • Some session-state transition (long background task completion? Bash hook PreToolUse error chain?) flipped the harness into a mode where every Stop hook trace is rendered The PreToolUse:Bash hook (check_cd_command.py) shows a similar artifact: PreToolUse:Bash hook error: [...]: No stderr output appears on every Bash invocation, but the hook is also passing cleanly (otherwise the Bash call would be blocked). Both hooks share the same 2>/dev/null redirect pattern in their commands.

Root Cause

In a single long-running session, the Stop hook trace [<command>]: No stderr output started displaying after every assistant turn — for ~30+ consecutive turns — despite the hook passing cleanly (exit 0, no stderr, no block). The same hook configuration in other sessions does not produce this trace. Once the noise starts in a session, it persists.

Code Example

"Stop": [
  {
    "hooks": [
      {
        "type": "command",
        "command": "uv run --script .claude/hooks/quality_gates.py 2>/dev/null"
      }
    ]
  }
]

---

$ '{"cwd":"...","stop_hook_active":false}' | uv run --script .claude/hooks/quality_gates.py
$ echo "exit: $LASTEXITCODE"
exit: 0

---

Stop hook feedback:
[uv run --script .claude/hooks/quality_gates.py 2>/dev/null]: No stderr output
RAW_BUFFERClick to expand / collapse

Claude Code bug: "Stop hook feedback: No stderr output" trace fires on every turn (session-scoped)

Summary

In a single long-running session, the Stop hook trace [<command>]: No stderr output started displaying after every assistant turn — for ~30+ consecutive turns — despite the hook passing cleanly (exit 0, no stderr, no block). The same hook configuration in other sessions does not produce this trace. Once the noise starts in a session, it persists.

Environment

  • Platform: Windows 11 Home (10.0.26200), PowerShell + Bash via Git Bash
  • Project: octopus (real-estate pipeline)
  • Model: claude-opus-4-7 (1M context)
  • Session duration: ~3 hours
  • Background tasks during session: yes — 2 long-running Bash background jobs (~85 min combined runtime for an Airtable mutation batch and a recovery script)

Hook config (.claude/settings.json)

"Stop": [
  {
    "hooks": [
      {
        "type": "command",
        "command": "uv run --script .claude/hooks/quality_gates.py 2>/dev/null"
      }
    ]
  }
]

The hook (.claude/hooks/quality_gates.py) imports claude_agent_sdk.StopHookInput, runs just typecheck on changed .py files and just find_dupes_win on changed source files, returns {"decision": "block", "reason": "..."} only on gate failure, otherwise exits 0 silently. Confirmed with direct invocation:

$ '{"cwd":"...","stop_hook_active":false}' | uv run --script .claude/hooks/quality_gates.py
$ echo "exit: $LASTEXITCODE"
exit: 0

Exit code 0, no stdout, no stderr.

What I see every assistant turn

Stop hook feedback:
[uv run --script .claude/hooks/quality_gates.py 2>/dev/null]: No stderr output

This appears as a system-level message at every turn end, regardless of what the hook actually returned. The hook is not blocking and not writing to stderr (the 2>/dev/null redirect would catch it anyway).

Expected behavior

Stop hook traces should only display when:

  • The hook returns a block decision, OR
  • The hook writes something useful to stderr, OR
  • Some verbose/debug flag is enabled

A passing hook that exits 0 with empty output should not produce visible feedback every turn.

Smell test — likely culprit

The rewakeSummary field in the settings schema is documented as:

@internal One-line summary shown to the user in the terminal when an asyncRewake hook exits with code 2. Defaults to "Stop hook feedback".

The hook here is not asyncRewake and does not exit 2 — but the harness is still rendering this trace with the "Stop hook feedback" summary string. So either:

  • A regression made the trace fire on non-asyncRewake Stop hooks
  • Some session-state transition (long background task completion? Bash hook PreToolUse error chain?) flipped the harness into a mode where every Stop hook trace is rendered

Session-only repro

The same hook config in fresh sessions of the same project does not show this trace. Something about long-session state (possibly background-task completion notifications interleaving with Stop hooks) seems to switch the harness's hook-trace rendering on. Once on, it stays on for the rest of the session.

What I tried in-session

  • Tightened the dedupe gate file filter to skip non-source files (no effect on trace)
  • Made the hook exit silently on pass with no stdout (no effect on trace)
  • Confirmed direct hook invocation works cleanly (exit 0, empty stderr)
  • Note: 2>/dev/null in the command was already there before; removing it would just let stderr pass through, but stderr is empty anyway

Related observation

The PreToolUse:Bash hook (check_cd_command.py) shows a similar artifact: PreToolUse:Bash hook error: [...]: No stderr output appears on every Bash invocation, but the hook is also passing cleanly (otherwise the Bash call would be blocked). Both hooks share the same 2>/dev/null redirect pattern in their commands.

Asks

  1. Is the "Stop hook feedback" trace supposed to render for non-asyncRewake hooks that pass silently?
  2. What session-state condition flips the harness into rendering every hook trace? (So we can avoid triggering it.)
  3. Is there a settings flag to suppress hook traces when there's no block / no useful output?

<signature>🦀 sent by Claude Code</signature>

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…

FAQ

Expected behavior

Stop hook traces should only display when:

  • The hook returns a block decision, OR
  • The hook writes something useful to stderr, OR
  • Some verbose/debug flag is enabled

A passing hook that exits 0 with empty output should not produce visible feedback every turn.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING