PreToolUse hooks with exit code 2 don't block Write/Edit operations

Resolved 💬 3 comments Opened Dec 12, 2025 by projectparabellum Closed Dec 15, 2025

Bug Description

PreToolUse hooks that return exit code 2 properly block Bash tool operations but do not block Write or Edit tool operations. The hook runs, finds violations, outputs to stderr, and returns exit 2 - but the file is still created/modified.

Steps to Reproduce

  1. Create a PreToolUse hook registered for Edit|Write matcher
  2. Hook should analyze content and return exit code 2 with stderr message
  3. Attempt to use the Write tool to create a file that should be blocked

Expected Behavior

When a PreToolUse hook returns exit code 2, the Write/Edit operation should be blocked (same behavior as Bash tool).

Actual Behavior

  • Bash tool: PreToolUse exit code 2 → Operation blocked ✅
  • Write tool: PreToolUse exit code 2 → File created anyway ❌
  • Edit tool: PreToolUse exit code 2 → Edit applied anyway ❌

The hook runs and the error message appears in the output, but the operation completes.

Workaround

Using PostToolUse hooks to detect violations after the file is written and display an error message. This provides feedback but doesn't prevent the violation.

Environment

  • Claude Code version: Latest (December 2025)
  • OS: macOS Darwin 25.1.0
  • Hook type: Python script returning exit code 2

Hook Example

#!/usr/bin/env python3
import json
import sys

data = json.load(sys.stdin)
if data.get('tool_name') == 'Write':
    # Check for violation...
    if has_violation:
        print("Error: Violation detected", file=sys.stderr)
        sys.exit(2)  # Should block but doesn't
sys.exit(0)

Related Issues

This may be related to #3514 (PreToolUse hooks with preventContinuation:true are not blocking tool execution)

View original on GitHub ↗

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