[BUG] Hook error messages shown on every tool call even when hooks exit 0
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
All three hook types (PreToolUse, PostToolUse, UserPromptSubmit) display "hook error" messages in the transcript on every tool call, even when the hook scripts exit 0 for non-matching commands. The hooks function correctly — they format files, validate commits, and block bad inputs — but Claude Code reports them as errors anyway.
The message is just "PreToolUse:Bash hook error" with no further detail. It appears twice per Bash call (once per registered hook) and once per Edit call.
What Should Happen?
Hooks that exit 0 should be silent. "hook error" should only appear for non-zero, non-2 exit codes (per the documentation). Exit 0 = allow, exit 2 = block.
Error Messages/Logs
● Bash(git status -u)
⎿ PreToolUse:Bash hook error
⎿ PreToolUse:Bash hook error
⎿ On branch feat/playground-design-sandbox
Your branch is up to date with 'origin/feat/playground-design-sandbox'.
...
● Update(~/Work/projects/workout/.claude/hooks/session-audit.sh)
⎿ Removed 1 line
⎿ PostToolUse:Edit hook error
❯ Did you check the files...
⎿ UserPromptSubmit hook error
Steps to Reproduce
- Create
.claude/settings.jsonwith hook configuration:
``json``
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "bash .claude/hooks/validate-commit.sh" }
]
}
]
}
}
- Create
.claude/hooks/validate-commit.sh:
``bash``
#!/usr/bin/env bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
echo "$COMMAND" | grep -qE '^git commit' || exit 0
if ! echo "$COMMAND" | grep -qP '#\d+'; then
echo "Commit message must include issue reference (#NN)." >&2
exit 2
fi
exit 0
- Run any Bash command via Claude Code (e.g., ask it to run
git status) - Observe "PreToolUse:Bash hook error" in transcript even though the hook exits 0
Note: The hook correctly blocks git commit without #NN (exit 2) and allows all other commands (exit 0). Manual testing confirms exit 0:
echo '{"tool_input":{"command":"git status"}}' | bash .claude/hooks/validate-commit.sh; echo $?
# outputs: 0
Claude Model
Opus
Is this a regression?
I don't know
Claude Code Version
2.1.76 (Claude Code)
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
- The error appears on every tool call, not just mismatched ones
- Actions still proceed (hooks are non-blocking when they exit 0) — the error label is cosmetic but noisy
- All hooks follow the same pattern: early
exit 0for non-matching commands,exit 2to block jqis installed and functional (tested), thoughjq --versionprints justjq-(no version number) — possibly relevant- Removing
set -euo pipefailfrom hooks did not fix the issue - Adding explicit
exit 0at end of all scripts did not fix the issue
This issue has 12 comments on GitHub. Read the full discussion on GitHub ↗