Stalled PostToolUse hook silently returns empty for all tool results, unrecoverable without full process restart
Summary
When a PostToolUse hook hangs, every subsequent tool call returns an empty result for the rest of the session — including Bash calls that cannot possibly produce empty output (e.g. echo XYZ), as well as Read, Glob, and ToolSearch. The tool appears to "succeed" but the result body is blank. There is no error, no timeout, and no signal to the model that the hook is the cause. The model cannot distinguish "command produced no output" from "a hook ate the result", so it wastes many turns retrying and misdiagnosing.
In my case the stalling hook was an rtk output-filter PostToolUse hook, but the core problem is general: a hung hook silently swallows all tool output with no diagnostic and no recovery short of killing the whole process.
Environment
- Claude Code CLI on macOS (Darwin 24.6.0)
- A
PostToolUsehook configured to pipe tool output through an external filter (rtk)
Steps to reproduce / what happens
- Early in the session, tool calls work. The hook is visibly active — e.g. an
lsresult came back wrapped with a banner:
[NOTE: rtk filtered this output (1077 → 631 tokens). Original preserved below in <ORIGINAL_OUTPUT>...]
- At some point (for me, right after a
Read/catof a markdown file) the hook stalls. - From that moment on, 100% of tool results are empty. Verified with
echo HELLO,date,printf,Read,ToolSearch— all return nothing.
Expected behavior
- A hung/failing
PostToolUse/Stophook should be subject to a hard timeout, and on timeout the original tool output should still be delivered (fail-open). - If a hook fails or times out, the model should receive an explicit error (e.g. "PostToolUse hook timed out / exited non-zero — raw tool output below"), not a silently empty result.
Actual behavior
- Empty result, no diagnostic, indefinitely, for every tool for the rest of the session.
Recovery (this part is the worst)
- Interrupting the conversation (Esc / Ctrl+C) does NOT fix it — same session, hook process still hung.
- Uninstalling / deleting the hook binary externally does NOT fix the running session — the hook config is already loaded in the running process's memory.
- Only a full CLI process restart recovers it. This is non-obvious and costs an entire session of context.
Suggested fixes
- Timeout + fail-open on hooks: enforce a hard timeout on
PostToolUse/Stophooks; on timeout, deliver the original tool output and log a warning. - Surface hook failures to the model: replace a hook-caused empty result with an explicit error string the model can reason about.
- Never silently swallow tool output: distinguish "command produced empty output" from "hook returned empty / errored".
- (Nice to have) Self-heal: if N consecutive tool results come back empty immediately after a hook runs, auto-disable that hook for the session and warn the user.
Impact
High friction. An entire session becomes unusable with no actionable signal, and the model burns turns retrying because there is no way to detect the root cause from inside the session.