Skip to content

Distinguish hook denial from hook error in PreToolUse output #31592

@r0bbbb

Description

@r0bbbb

Problem

When a PreToolUse hook intentionally blocks a command (exit code 2), the output is labeled:

PreToolUse:Bash hook error: [message]

This is misleading — the hook didn't error, it intentionally denied the operation. There's no way to distinguish between "the hook crashed" and "the hook blocked this command by design."

Use case

We use PreToolUse hooks as a CLI governance layer — enforcing read-only AWS access, blocking destructive git operations, preventing production writes, etc. These are intentional policy denials, not errors. The "hook error" label confuses users into thinking something is broken.

Proposed solution

Differentiate the label based on exit code or hook output:

  • Exit 2 (blocking denial): PreToolUse:Bash hook denied: [stderr message]
  • Non-zero other (actual error): PreToolUse:Bash hook error: [stderr message]

Alternatively, allow hooks to set a custom label via structured JSON output (e.g., {"label": "BLOCKED", "message": "..."}).

Current workaround

We prefix our stderr messages with BLOCKED: to make intent clear, but the outer "hook error" label still appears and causes confusion.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions