PreToolUse hooks with preventContinuation:true are not blocking tool execution

Resolved 💬 8 comments Opened Jul 15, 2025 by cworsnup13 Closed Feb 28, 2026

Bug Report

Version: Claude Code 1.0.51
Platform: macOS (Darwin 24.5.0)

Summary

PreToolUse hooks that return {"continue": false, "stopReason": "..."} are not preventing tool execution despite Claude Code correctly parsing and processing the hook response with preventContinuation: true.

Expected Behavior

When a PreToolUse hook returns {"continue": false}, the tool should not be executed and the user should see the stopReason message instead.

Actual Behavior

The hook is executed correctly and returns the blocking response, but the tool execution continues anyway.

Debug Output Evidence

The debug logs clearly show the issue:

[DEBUG] Hook command completed with status 2: /Users/cworsnup/.claude/custom/bash_tool_prehook.sh
[DEBUG] Hook stdout: {"continue": false, "stopReason": "Use ~/globalvenv/bin/python3 instead of installing packages with pip3."}
[DEBUG] Successfully parsed and validated hook JSON output
[DEBUG] Parsed JSON output from hook: {"continue":false,"stopReason":"Use ~/globalvenv/bin/python3 instead of installing packages with pip3."}
[DEBUG] Processed hook result: {"preventContinuation":true,"stopReason":"Use ~/globalvenv/bin/python3 instead of installing packages with pip3."}
[DEBUG] Bash tool invoked with command: pip3 install requests

Note the last line: despite preventContinuation: true, the Bash tool is still invoked.

Reproduction Steps

  1. Create a PreToolUse hook script that returns {"continue": false, "stopReason": "..."}
  2. Configure the hook in settings for the Bash tool
  3. Attempt to run a command that the hook should block
  4. Observe that the tool executes despite the hook rejection

Hook Script Example

#\!/bin/bash
json_input=$(cat)
command=$(echo "$json_input" | grep -o '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"command"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')

if [[ "$command" == *"pip3 install requests"* ]]; then
    echo '{"continue": false, "stopReason": "Use ~/globalvenv/bin/python3 instead of installing packages with pip3."}'
    exit 2
fi

echo "$json_input"
exit 0

Additional Context

  • The hook itself is working correctly (proper JSON response, correct exit codes)
  • The Claude Code hook system is parsing and processing the response correctly
  • The issue appears to be in the final step where preventContinuation: true should prevent tool execution
  • This appears to be a regression or unimplemented feature in the hook system

Impact

This prevents users from effectively blocking dangerous or unwanted tool executions via hooks, which is a critical security and workflow management feature.

View original on GitHub ↗

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