Claude Code PreToolUse Bash Hook Error
When Claude Code shows PreToolUse:Bash hook error after a successful exit 0 hook, emit echo {} or modern hookSpecificOutput JSON instead of silent exit.
Quick answer
Match the transcript label PreToolUse:Bash hook error when the Bash tool still runs. On early-exit paths that currently exit 0 with no stdout, print a no-op JSON object with echo "{}" then exit 0. If the hook returns legacy {"decision":"allow"}, switch to the modern hookSpecificOutput permissionDecision allow JSON instead. Confirm the hook still exits 0 by hand. This is a false-positive label on successful hooks, not a weekly limit and not a reason to delete every hook.
On this page
What we're seeing
- The exact transcript label is PreToolUse:Bash hook error. Close variants include PostToolUse:Bash hook error and PostToolUse:Edit hook error.
- Independent January and March 2026 first-hand reports on anthropics/claude-code quote that label while hooks exit 0 and still allow the tool.
- Common triggers are silent early exit 0 with empty stdout, or legacy decision allow JSON that Claude Code still paints as an error label.
- A real blocking failure is different: exit 2 with stderr, or a permission deny that stops the tool. Those are not this false-positive leftover.
- Weekly limit, overloaded, and rate-limit waits are out of scope for this fingerprint.
Start here
Try these first
Fix 1
Confirm the hook error label
Match the transcript wording and whether the tool still ran before rewriting hooks.
- Read the transcript. This guide is for PreToolUse:Bash hook error, including PostToolUse:Bash hook error or PostToolUse:Edit hook error when the tool still completed.
- If the tool was blocked and stderr shows a real validation message with exit 2, stop here. That is a deliberate block, not the false-positive label.
- Note which matcher and script printed nothing on the allow path.
Applies to Windows, Mac, Desktop
Fix 2
Print empty JSON on silent allow exits
March 2026 first-hand reports cleared the label when early-exit paths printed echo "{}" before exit 0 instead of producing no stdout. Empty stdout is what the runner treats like an error display condition even when the exit code is 0.
- Open the hook script that exits early for non-matching tools or commands.
- On every silent allow path, print a no-op JSON object, for example echo "{}", then exit 0.
- Keep real block paths on exit 2 with a clear stderr reason.
- Re-run the same Bash or Edit action and check whether PreToolUse:Bash hook error is gone.
Applies to Windows, Mac, Desktop
Fix 3
Use modern hookSpecificOutput allow JSON
January 2026 first-hand workaround reports say legacy {"decision":"allow"} can still show the phantom error label, while modern hookSpecificOutput with permissionDecision allow does not.
- If the hook prints JSON to allow the tool, stop using legacy decision allow alone.
- Print modern structured output with continue true and hookSpecificOutput.hookEventName set to PreToolUse plus permissionDecision allow.
- Save the script, trigger the same tool once, and confirm the transcript no longer shows PreToolUse:Bash hook error.
Applies to Windows, Mac, Desktop
Fix 4
Verify the hook exit code by hand
Reporters pipe sample tool JSON into the script locally to prove exit 0 before blaming Claude Code. That separates a broken script from the false-positive label.
- From the project root, pipe a sample tool JSON object into the hook script the same way Claude Code would.
- Confirm the exit code is 0 on the allow path and that stdout is either {} or valid modern hook JSON.
- If the local exit code is non-zero, fix the script first. The UI label is then a real hook failure.
Applies to Windows, Mac, Desktop
Device notes
- Windows
- The same echo "{}" and modern JSON leftovers apply on Windows hosts. Prefer absolute interpreter paths in settings.json if the hook command fails before it can print JSON.
- Mac
- macOS Bash or zsh hook scripts still need a stdout JSON object on silent allow paths.
- Desktop
- Claude Code CLI on desktop is the surface for this transcript label. Linux desktop builds use the same leftovers.
Official information
Checked on 6 September 2026, Claude Code community issues that quote PreToolUse:Bash hook error describe a false-positive label when hooks exit 0 with empty stdout or legacy allow JSON. Try-today leftovers come from independent January–March 2026 first-hand GitHub reports (echo "{}" on silent exits; modern hookSpecificOutput permissionDecision allow), not from an Anthropic Help article that names this exact sentence.
Sources
- PreToolUse hook shows error label even for successful exit 0 hook runs community
- Hooks: hook error label shown when hooks exit cleanly with code 0 and no output community
- Hook error messages shown on every tool call even when hooks exit 0 community
- PreToolUse hook shows error label even when hook passes exit 0 community
Keep troubleshooting
Related problems
Claude
Claude Code Tool Call Could Not Be Parsed Retry Failed
Windows · Mac · DesktopUpdated Sep 13, 2026
WhatsApp Restore Stuck at 69 Percent
Android · MobileUpdated Sep 23, 2026
Cursor
Cursor No Resource Accessor Found for Composer
Windows · Mac · DesktopUpdated Sep 11, 2026
Claude
Claude Code Connection Dropped ECONNRESET
Windows · Mac · DesktopUpdated Sep 19, 2026