[BUG] PreToolUse hook systemMessage not visible to Claude (assistant) when blocking

Resolved 💬 4 comments Opened Feb 17, 2026 by SebRogala Closed Mar 17, 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?

When a PreToolUse hook blocks an operation and returns a systemMessage with a detailed error explanation, the user sees the message in the UI, but Claude (the assistant) only sees "Blocked by hook" - not the actual systemMessage content.

This makes it impossible for Claude to understand WHY a tool was blocked and self-correct. The assistant has to guess or ask the user to copy-paste the error message.

What Should Happen?

The systemMessage returned by the hook should be included in the <system-reminder> that Claude receives after a block, like:

<system-reminder>
PreToolUse:Bash hook blocked this operation:
**[commit-message-format]**
Invalid commit message format

All commits must follow: CRE-X (type): description
The `(type):` part is REQUIRED.
</system-reminder>

Instead, Claude only sees:

<system-reminder>
PreToolUse:Bash hook blocking error from command: "python3 .../hooks/pretooluse.py": Blocked by hook
</system-reminder>

Technical Details

The hook correctly returns:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny"
  },
  "systemMessage": "**[commit-message-format]**\n Invalid commit message...(detailed message)"
}

The systemMessage is surfaced to the user in the TUI, but NOT to the assistant in the system-reminder.

Why This Matters

  1. Self-correction: Claude can't fix issues if it doesn't know what's wrong
  2. Workflow efficiency: User has to manually explain what the hook said
  3. Plugin ecosystem: Hook authors expect systemMessage to guide Claude's behavior

Related Issues

  • #10062 - permissionDecisionReason not surfaced (closed as dup, not fixed)
  • #9630 - Block reason not shown in -p mode (different case)
  • #16289 - systemMessage not displayed for SubagentStop (same root cause)

Steps to Reproduce

  1. Create a PreToolUse hook that returns systemMessage on deny (e.g., using hookify plugin)
  2. Trigger the hook (e.g., run a git commit with wrong format)
  3. Observe: User sees the detailed message, Claude only sees "Blocked by hook"

Claude Code Version

Latest (2.x)

Platform

Linux (WSL2)

Operating System

Linux

Terminal/Shell

zsh

View original on GitHub ↗

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