PreToolUse hooks with Edit|Write matcher silently never invoked for an entire session (bypassPermissions, v2.1.195/196) while Bash-matched hooks fire normally

Open 💬 0 comments Opened Jul 6, 2026 by fbserg

Summary

In a session running under permissionMode: bypassPermissions, PreToolUse hooks with an Edit|Write matcher were never invoked at all for the entire session, while PreToolUse hooks with a Bash matcher fired normally in the same session. This silently disabled a safety hook (an edit-count guard that hard-denies past a threshold) for 99 consecutive Edit/Write tool calls.

This appears distinct from existing reports: not #13744 (hooks fire for Edit/Write but fail to block — here they never executed), not #69970 (Bash hooks not firing — here Bash hooks worked fine), and not #71950 (denials under bypassPermissions — here the opposite, no hook ran at all).

Environment

  • Claude Code 2.1.195, upgraded mid-session to 2.1.196 (behavior identical before and after the upgrade)
  • macOS (Darwin 25.x)
  • permissionMode: bypassPermissions for the whole session
  • Hooks registered in ~/.claude/settings.json since well before the session (verified via file mtime and config-repo git history):
  • PreToolUse matcher Edit|Write → two scripts (a settings-file guard and an edit-count guard, both plain Python, both executable, both known-working in other sessions)
  • PreToolUse matcher Bash → separate scripts

Evidence (from the session transcript JSONL)

  • 99 top-level Edit/Write tool_use entries (no sidechains: isSidechain:true count = 0)
  • 0 hook-execution attachments for PreToolUse:Edit or PreToolUse:Write
  • 97 hook-execution attachments for PreToolUse:Bash (logged as normal hook_success entries throughout the same session)
  • The edit-guard's warn/deny message strings appear nowhere in the transcript (so it never ran and allowed — it never ran at all)
  • No override mechanism was used (the guard's opt-out marker file did not exist; opt-out phrase absent from transcript)
  • The same hooks fire normally for Edit/Write in other sessions on the same machine

Expected

PreToolUse hooks run for every matched tool call regardless of permission mode (bypassPermissions skips permission prompts, not hooks — hooks are the only enforcement layer left in that mode, which makes silent non-invocation a safety problem).

Actual

Edit|Write-matched PreToolUse hooks silently never executed for an entire session; Bash-matched PreToolUse hooks in the same session executed normally.

Notes

  • Because the failure is silent (no error, no log, tool calls proceed), users have no signal that their guard hooks are inactive. Even if the root cause is an edge case, a visible warning when a registered hook is skipped/not invoked would mitigate the safety impact.
  • Happy to provide redacted transcript excerpts (hook-execution attachment counts, tool_use entries) on request.

View original on GitHub ↗