[BUG] PreToolUse hooks: exit code 2 (block) shows misleading "error" prefix — add a clean "info" block mode

Resolved 💬 2 comments Opened Apr 14, 2026 by venks-warrior Closed May 23, 2026

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?

Component: Hooks / PreToolUse

Severity: Low (UX/cosmetic)

Description:

When a PreToolUse hook exits with code 2 to block a command, Claude Code wraps the stderr output in this format:

The Error: PreToolUse:Bash hook error: prefix is misleading because:

  1. There is no error — the hook intentionally blocked the command to run a pre-flight check (in our case, an accessibility scan before git add/commit/push)
  2. Users see "Error" and think something is broken
  3. The long hook command path adds noise and confusion
  4. There's no way to suppress or customize this prefix from the hook script

Current behavior:

┌───────────┬─────────┬───────────────────────────────────────────────────────────────┐
│ Exit code │ Meaning │ Display │
├───────────┼─────────┼───────────────────────────────────────────────────────────────┤
│ 0 │ Allow │ No message shown │
├───────────┼─────────┼───────────────────────────────────────────────────────────────┤
│ 2 │ Block │ Error: PreToolUse:Bash hook error: [<full command>]: <stderr> │
└───────────┴─────────┴───────────────────────────────────────────────────────────────┘

What Should Happen?

Expected / requested behavior:

Provide a way for hooks to block a command with a clean informational message, not an error. For example:

  • A new exit code (e.g., exit 3) that means "block with info" and displays stderr without the error prefix
  • Or a way to set the display format via a header line in stderr (e.g., @@hook-info: <message>)
  • Or a configuration option in settings.json to set displayMode: "info" | "error" per hook

Example desired output:
🔍♿ a11y scan triggered · scanning 1 component(s) before git add ...

Instead of:
Error: PreToolUse:Bash hook error:

Use case:

We built a pre-commit skill that hooks into git add, git commit, and git push via a PreToolUse hook. The hook intentionally blocks the git
command, based on logic of skill.
error condition. The "error" prefix confuses developers into thinking the hook itself is broken.

Environment:

  • Claude Code CLI
  • macOS / Darwin 25.4.0
  • Hook type: PreToolUse → Bash matcher

Error Messages/Logs

Steps to Reproduce

  1. Create a PreToolUse hook in .claude/settings.json:

{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/test-hook.sh"
}
]
}
]
}
}

  1. Create the hook script at .claude/hooks/test-hook.sh:

#!/usr/bin/env bash
set -euo pipefail

COMMAND="$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_input',{}).get('command',''))" 2>/dev/null || echo "")"

# Block any git add command with an informational message
if echo "$COMMAND" | grep -qE '\bgit\s+add(\s|$)'; then
echo "Running pre-stage scan before git add..." >&2
exit 2
fi

exit 0

  1. Make the script executable:

chmod +x .claude/hooks/test-hook.sh

  1. In Claude Code, ask the assistant to run:

git add some-file.txt

Actual result:
Error: PreToolUse:Bash hook error: [bash "$CLAUDE_PROJECT_DIR"/.claude/hooks/test-hook.sh]: Running pre-stage scan before git add...

Expected result:
Running pre-stage scan before git add...

The Error: PreToolUse:Bash hook error: [bash "$CLAUDE_PROJECT_DIR"/.claude/hooks/test-hook.sh]: prefix should not appear when the hook intentionally blocks
a command (exit 2) for informational purposes. The hook is working as designed — it is not an error condition.

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.104

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗