[BUG] One malformed hooks entry silently disables ALL hooks for that event (UserPromptSubmit) — valid sibling hooks die with zero feedback until the file is hand-fixed

Status Open
Reported on v2.1.217
Maintainer reply None cached
Activity 1 comment · opened Jul 30, 2026

Environment

  • Claude Code engine 2.1.217 → 2.1.219, Claude desktop app 1.24012.1 → 1.24012.9 (entrypoint: claude-desktop)
  • macOS (Darwin 25.x), Apple Silicon
  • Hooks configured in ~/.claude/settings.json

Summary

**One structurally malformed entry in the hooks.UserPromptSubmit array silently disables all hooks for that event** — including other, perfectly valid entries that had been working for days. No error, no warning, nothing in any log. The valid hooks stay dead on every subsequent message until the malformed entry is fixed; restarting the app or even rebooting the machine does not help (the file is re-parsed per message, and the parse presumably keeps failing the same way).

Timeline (all timestamps EDT, reconstructed from session transcripts to the second)

  • 07-24 16:10 — a simple "clock" hook (unconditional additionalContext injection) added to UserPromptSubmit via the built-in Edit tool, correct structure. Works immediately: 88 successful injections over ~50 hours, verified via hook_additional_context attachments in session JSONL.
  • 07-26 20:49:06 — a second hook was appended by a script using a bare non-atomic open(path,'w') + json.dump(), and with the wrong shape: the hook object {"type":"command","command":...,"timeout":1} was placed directly in the UserPromptSubmit array, missing the {"matcher": "", "hooks": [ ... ]} wrapper that all sibling entries have.
  • 07-26 20:55:33 — first user message after the write: zero hooks fired. From this moment, across 158+ real user turns over three days, the previously reliable clock hook never fired again (0/158, verified structurally in transcripts, not by text grep).
  • 07-29 — full machine reboot: still dead.
  • 07-30 19:10 — the malformed entry was wrapped correctly (everything else byte-identical). The very next message fired all hooks again — no app restart needed.

Expected behavior

  • Hook entries should be validated individually: a malformed entry should be skipped (ideally with a visible warning in /doctor, a log line, or a one-time notice), and the remaining valid entries should keep working.
  • Silently dropping the whole event's hook list turns one bad edit into an invisible, days-long outage of unrelated hooks. The failure mode is particularly nasty because nothing anywhere reports it — we only found it by diffing the array's entries against each other.

Possibly related

#56631, #49989, #8810 describe "UserPromptSubmit hooks silently not firing" in various scenarios and were closed as not-planned. At least some of those reports may share this root cause: any tool or hand edit that writes a structurally-off entry kills the whole event's hooks with zero feedback. A per-entry validate-and-warn would likely resolve that class of reports.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗