PostToolUse hooks don't execute for failed Bash commands

Resolved 💬 9 comments Opened Aug 22, 2025 by Twizzes Closed Jan 7, 2026

Summary

PostToolUse hooks configured to monitor Bash tool execution are skipped entirely when the Bash command fails (exits with non-zero status). This limitation prevents hooks from providing useful feedback or context about failed commands.

Expected Behavior

PostToolUse hooks should execute regardless of whether the underlying tool call succeeds or fails, allowing hooks to:

  • Provide additional context for failures
  • Log failed operations
  • Suggest remediation steps
  • Perform cleanup after failed commands

Actual Behavior

PostToolUse hooks are completely skipped when Bash commands fail, as evidenced by the absence of hook execution debug output.

Reproduction Steps

  1. Configure a PostToolUse hook for Bash in settings.json:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/test-hook.sh"
          }
        ]
      }
    ]
  }
}
  1. Create a simple test hook script:
#!/bin/bash
echo "PostToolUse hook executed" >&2
exit 0
  1. Run Claude Code with debug mode: claude --debug
  1. Test with successful Bash command:
ls  # This will show PostToolUse hook execution in debug output
  1. Test with failing Bash command:
ls nonexistent-file.txt  # This will NOT show PostToolUse hook execution

Debug Output Evidence

Successful command (ls) shows PostToolUse hooks executing:

[DEBUG] Executing hooks for PostToolUse:Bash
[DEBUG] Getting matching hook commands for PostToolUse with query: Bash
[DEBUG] Found 1 hook matchers in settings
[DEBUG] Matched 1 unique hooks for query "Bash" (1 before deduplication)
[DEBUG] Found 1 hook commands to execute
[DEBUG] Executing hook command: /path/to/hook.sh with timeout 60000ms
[DEBUG] Hook command completed with status 0

Failed command (ls nonexistent-file.txt) shows NO PostToolUse hook execution:

[DEBUG] Bash tool invoked with command: ls nonexistent-file.txt
● Bash(ls nonexistent-file.txt)
  ⎿  Error: ls: cannot access 'nonexistent-file.txt': No such file or directory
[DEBUG] MCP server "ide": Calling MCP tool: getDiagnostics
# Notice: No PostToolUse hook debug output at all

Workaround

The only current workaround is to use commands that don't fail but simulate the failure output:

echo "Error: ls: cannot access 'test': No such file or directory"
# This successfully triggers PostToolUse hooks because exit code = 0

Use Case Impact

This limitation significantly impacts useful hook scenarios such as:

  • Directory context hooks: Providing current working directory when "No such file or directory" errors occur
  • Command validation: Logging or analyzing failed operations
  • Error enhancement: Adding contextual information to help debug failures
  • Cleanup operations: Performing cleanup after failed commands

Environment

  • Claude Code version: Latest (as of 2025-01-22)
  • OS: Linux (WSL2)
  • Hook configuration: PostToolUse with Bash matcher

Documentation Impact

The hooks reference documentation doesn't mention this limitation. It should clarify whether PostToolUse hooks are intended to skip failed tool calls or if this is a bug.

Request

Please either:

  1. Fix the behavior so PostToolUse hooks execute for failed tool calls, OR
  2. Document this limitation clearly in the hooks reference documentation, OR
  3. Provide an alternative hook event that triggers for failed tool calls (e.g., PostToolFailure)

View original on GitHub ↗

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