PostToolUse async hook invocations partially dropped on consecutive Write/Edit batches (Windows, 2.1.139)

Status Open
Reported on v2.1.139
Maintainer reply None cached
Activity 2 comments · opened Jul 19, 2026

Summary

PostToolUse hook invocations are partially dropped when a session performs consecutive or parallel Write/Edit tool calls. In a measured batch, only 6 of 12 matching edits triggered the hook. No error is surfaced anywhere — the missing invocations simply never happen.

This is distinct from the "hooks never fire" reports (#55644, closed as dup of #6305): wiring is correct and the hook does fire — just not for every matched tool call.

Environment

  • Claude Code 2.1.139 (Windows desktop app)
  • Windows 11 Pro 10.0.26200
  • Hook runtime: Windows PowerShell 5.1

Configuration (~/.claude/settings.json, sanitized)

"PostToolUse": [
  {
    "matcher": "Write|Edit",
    "hooks": [
      {
        "type": "command",
        "command": "powershell -NoProfile -File C:/Users/XXX/.claude/hooks/mirror-plan.ps1",
        "async": true,
        "timeout": 30,
        "statusMessage": "Mirroring memory"
      }
    ]
  }
]

The hook script reads the JSON payload from stdin and appends a line to a local log file for every invocation whose file_path matches a directory filter, then scps the file to a backup host.

Observed behavior

  • A session performing a batch of 12 Edit/Write calls to files matching the filter produced only 6 log entries (hook script logs immediately after the path filter, before any network I/O — so the missing 6 were never invoked, not failed mid-run).
  • Occasionally a single, isolated Edit also produces no invocation (observed same day in a different session; same config, hook proven working minutes later via manual stdin invocation and via other edits).
  • When invocations do run, they complete quickly (<2 s) and exit 0, well within the 30 s timeout.
  • No errors in the session transcript, no partial log lines, nothing to indicate the dropped calls ever started.

Expected behavior

One hook invocation per matched tool call — or, if async hooks are intentionally coalesced/debounced under load, documentation of that behavior (it currently silently breaks "mirror on every write"-style hooks).

Workaround

Post-batch reconciliation: count log entries vs. edits performed, then manually re-invoke the hook (pipe the JSON payload to the script via stdin) for the files that were missed.

Notes

  • Possibly related to async: true scheduling; not yet tested whether synchronous hooks drop calls the same way.
  • Ref: #55644 (closed as duplicate of #6305 — that report was "never fires"; this one is "fires for a subset").

View original on GitHub ↗

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