claude-code - 💡(How to fix) Fix [BUG] PreToolUse hook permissionDecision "allow" does not suppress native permission prompt in interactive mode (v2.1.119) [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#52822Fetched 2026-04-25 06:19:59
View on GitHub
Comments
2
Participants
2
Timeline
8
Reactions
0
Timeline (top)
labeled ×6commented ×2

Error Message

Hook stdout (captured via hexdump, confirmed valid JSON): {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"<reason>"}}

Debug log excerpt from ~/.claude/debug/<session>.txt:

[DEBUG] Hooks: Checking first line for async: {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"..."}} [DEBUG] Hooks: Parsed initial response: {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"..."}} [DEBUG] Successfully parsed and validated hook JSON output [INFO] [Stall] tool_dispatch_start tool=Write toolUseId=toolu_... permissionDecisionMs=<N>

The "Successfully parsed and validated" line confirms JSON acceptance. However, permissionDecisionMs shows the delay corresponds to the native prompt wait (>60s until user presses Yes), not the hook response time (which was <1s).

When PermissionRequest event is added as a second hook target with identical JSON structure: Hook PermissionRequest:Write (PermissionRequest) error: Failed to run: Hook returned incorrect event name: expected 'PermissionRequest' but got 'PreToolUse'

After patching the hook to emit hookEventName dynamically from stdin's hook_event_name field, PermissionRequest parses successfully — but the native prompt still appears.

Root Cause

Not filing this separately since it may be the same root cause — the hook system and the permission prompt suppression appear to be decoupled in 2.1.119.

Fix Action

Fix / Workaround

[DEBUG] Hooks: Checking first line for async: {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"..."}} [DEBUG] Hooks: Parsed initial response: {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"..."}} [DEBUG] Successfully parsed and validated hook JSON output [INFO] [Stall] tool_dispatch_start tool=Write toolUseId=toolu_... permissionDecisionMs=<N>

After patching the hook to emit hookEventName dynamically from stdin's hook_event_name field, PermissionRequest parses successfully — but the native prompt still appears.


Patched the hook to emit `hookEventName` dynamically based on `hook_event_name` field from stdin. PermissionRequest then parsed successfully (confirmed via "Successfully parsed and validated hook JSON output" in debug log), but **the native prompt still appeared**.

Code Example

Hook stdout (captured via hexdump, confirmed valid JSON):
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"<reason>"}}

Debug log excerpt from ~/.claude/debug/<session>.txt:

[DEBUG] Hooks: Checking first line for async: {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"..."}}
[DEBUG] Hooks: Parsed initial response: {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"..."}}
[DEBUG] Successfully parsed and validated hook JSON output
[INFO] [Stall] tool_dispatch_start tool=Write toolUseId=toolu_... permissionDecisionMs=<N>

The "Successfully parsed and validated" line confirms JSON acceptance. However, permissionDecisionMs shows the delay corresponds to the native prompt wait (>60s until user presses Yes), not the hook response time (which was <1s).

When PermissionRequest event is added as a second hook target with identical JSON structure:
Hook PermissionRequest:Write (PermissionRequest) error:
Failed to run: Hook returned incorrect event name: expected 'PermissionRequest' but got 'PreToolUse'

After patching the hook to emit hookEventName dynamically from stdin's hook_event_name field, PermissionRequest parses successfully — but the native prompt still appears.

---

cat > /tmp/fake-allow-hook.sh <<'EOF'
#!/bin/bash
# Discard stdin (hook event payload)
cat > /dev/null
# Emit well-formed allow decision per hooks reference
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"reproduction test"}}'
exit 0
EOF
chmod +x /tmp/fake-allow-hook.sh

---

mkdir -p ~/.claude
cat > ~/.claude/settings.json <<'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|Bash|MultiEdit",
        "hooks": [
          { "type": "command", "command": "/tmp/fake-allow-hook.sh" }
        ]
      }
    ]
  }
}
EOF

---

claude --debug hooks

---

Create a file at /tmp/repro.txt with the content "hello". Use the Write tool.

---

Hook returned incorrect event name: expected 'PermissionRequest' but got 'PreToolUse'
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

A PreToolUse hook (type: "command") that exits with code 0 and emits a well-formed hookSpecificOutput with permissionDecision: "allow" on stdout does not suppress the native Do you want to X? permission prompt in interactive mode.

The hook executes correctly, stdout JSON is parsed successfully by Claude Code (confirmed in debug log with "Successfully parsed and validated hook JSON output"), but the native UI prompt is still shown to the user, requiring manual Yes/No confirmation.

The documented behavior per hooks reference is that permissionDecision: "allow" bypasses the permission system. This appears to be a regression relative to #28812, which was confirmed resolved on v2.1.59.

Impact: programmatic approval workflows (e.g. remote approval UIs, audit-gated tool execution, compliance logging) cannot rely on hooks to gate tool calls without a redundant native confirmation from the user. Hook exit 2 (deny) correctly blocks the tool — only the allow suppression path is broken.

What Should Happen?

When a PreToolUse hook returns hookSpecificOutput with permissionDecision: "allow" and exits 0, Claude Code should execute the tool without displaying the native permission prompt.

This matches:

  • The documented behavior in the hooks reference: "allow: Bypass permission system and allow"
  • The resolved behavior in #28812, confirmed working on v2.1.59
  • The stated SDK semantics: "bypassPermissions: Auto-approves all tool uses without prompts. Hooks still execute and can block operations if needed."

Error Messages/Logs

Hook stdout (captured via hexdump, confirmed valid JSON):
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"<reason>"}}

Debug log excerpt from ~/.claude/debug/<session>.txt:

[DEBUG] Hooks: Checking first line for async: {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"..."}}
[DEBUG] Hooks: Parsed initial response: {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"..."}}
[DEBUG] Successfully parsed and validated hook JSON output
[INFO] [Stall] tool_dispatch_start tool=Write toolUseId=toolu_... permissionDecisionMs=<N>

The "Successfully parsed and validated" line confirms JSON acceptance. However, permissionDecisionMs shows the delay corresponds to the native prompt wait (>60s until user presses Yes), not the hook response time (which was <1s).

When PermissionRequest event is added as a second hook target with identical JSON structure:
Hook PermissionRequest:Write (PermissionRequest) error:
Failed to run: Hook returned incorrect event name: expected 'PermissionRequest' but got 'PreToolUse'

After patching the hook to emit hookEventName dynamically from stdin's hook_event_name field, PermissionRequest parses successfully — but the native prompt still appears.

Steps to Reproduce

  1. Create a minimal "always allow" hook script:
cat > /tmp/fake-allow-hook.sh <<'EOF'
#!/bin/bash
# Discard stdin (hook event payload)
cat > /dev/null
# Emit well-formed allow decision per hooks reference
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"reproduction test"}}'
exit 0
EOF
chmod +x /tmp/fake-allow-hook.sh
  1. Configure Claude Code user settings:
mkdir -p ~/.claude
cat > ~/.claude/settings.json <<'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|Bash|MultiEdit",
        "hooks": [
          { "type": "command", "command": "/tmp/fake-allow-hook.sh" }
        ]
      }
    ]
  }
}
EOF
  1. Start Claude Code with hooks debug:
claude --debug hooks
  1. In the Claude Code prompt, request a Write operation:
Create a file at /tmp/repro.txt with the content "hello". Use the Write tool.
  1. Observe: the native Do you want to create repro.txt? 1. Yes / 2. Yes, allow all / 3. No prompt appears even though the hook has already returned allow and Claude Code has logged Successfully parsed and validated hook JSON output.

  2. Expected: no native prompt, Write executes directly.
    Actual: native prompt shown, execution stalls until manual confirmation.

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.59

Claude Code Version

2.1.119 (Claude Code)

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

Other

Additional Information

Environment details

  • Terminal: Konsole (KDE Plasma 6) on NixOS 25.05 — dropdown did not include Konsole as an option
  • Install method: nix profile install github:sadjow/claude-code-nix (self-contained Bun binary, ~180MB, auto-updated hourly from Anthropic releases)
  • Subscription: Claude Max (via organization)
  • Shell: bash (via nix-shell)

Additional testing performed

1. PermissionRequest event test:

Added PermissionRequest as a second hook target with identical JSON structure. Claude Code rejected the payload with:

Hook returned incorrect event name: expected 'PermissionRequest' but got 'PreToolUse'

Patched the hook to emit hookEventName dynamically based on hook_event_name field from stdin. PermissionRequest then parsed successfully (confirmed via "Successfully parsed and validated hook JSON output" in debug log), but the native prompt still appeared.

2. --permission-mode bypassPermissions CLI flag:

When this flag was set, the hook was not invoked at all — no hook execution visible in debug log, no stdin consumed by the hook script. This contradicts the documented SDK behavior: "bypassPermissions: Auto-approves all tool uses without prompts. Hooks still execute and can block operations if needed." (SDK permissions docs).

Not filing this separately since it may be the same root cause — the hook system and the permission prompt suppression appear to be decoupled in 2.1.119.

3. Fresh state reproduction:

Reproduced on a clean ~/.claude/ (single settings.json, no prior hooks, no plugins, no MCP servers loaded). Bug is not state-dependent.

Related issues

  • #28812 — confirmed working on v2.1.59; possible regression introduced between 2.1.59 and 2.1.119
  • #41615 — similar symptom scoped to .claude/ sensitive paths; this issue is broader (all Write/Edit/Bash/MultiEdit operations)
  • #15897updatedInput field ignored on v2.0.76 (separate but related hook output parsing issue)
  • #13339 — VS Code extension ignores permissionDecision: "ask" (different decision value, similar UI suppression gap)

Expected troubleshooting if helpful

Happy to provide:

  • Full ~/.claude/debug/<session>.txt log (redacted for paths)
  • Additional test matrix across hook event types (PreToolUse, PermissionRequest)
  • Test with various matcher patterns (empty, explicit, regex)
  • Sample hook in other languages (Python, Rust) confirming same behavior

extent analysis

TL;DR

The issue can be fixed by investigating and addressing the regression introduced between Claude Code versions 2.1.59 and 2.1.119, specifically focusing on the hook system and permission prompt suppression.

Guidance

  1. Review changes between versions: Examine the changelog and code differences between 2.1.59 and 2.1.119 to identify potential causes of the regression.
  2. Verify hook execution and parsing: Confirm that the hook is executing correctly and its output is being parsed as expected by Claude Code, using the provided debug logs.
  3. Test with different hook event types: Perform additional testing with various hook event types (e.g., PermissionRequest) to determine if the issue is specific to PreToolUse or a broader problem.
  4. Check for conflicts with other settings or plugins: Investigate whether other settings, plugins, or configurations might be interfering with the hook system or permission prompt suppression.

Example

No code snippet is provided as the issue seems to be related to the interaction between Claude Code and its hooks, rather than a specific code error.

Notes

The issue appears to be a regression, and resolving it may require identifying and reverting changes made between versions 2.1.59 and 2.1.119 that affect the hook system and permission prompt suppression.

Recommendation

Apply a workaround by downgrading to version 2.1.59, where the issue was confirmed to be resolved, until the regression can be properly addressed in a future version.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] PreToolUse hook permissionDecision "allow" does not suppress native permission prompt in interactive mode (v2.1.119) [2 comments, 2 participants]