Paths Subjects Questions Quizzes Pricing Search
Advanced Open Free

What Exit Code 2 Does to a Hook's Tool Call

A team writes a PreToolUse hook meant to block any Bash call containing rm -rf. During testing, a bug in the script's exit-code handling causes it to exit with status code 2 on a totally harmless command that doesn't match the dangerous pattern — and the script prints nothing to stdout.

Given how Claude Code interprets hook exit codes, what happens to that harmless tool call?

Solution

The correct answer is "It's blocked — exit 2 is a blocking error unless overridden."

Claude Code treats a hook's exit code as its decision mechanism: exit code 0 means proceed (optionally paired with JSON output expressing a decision), while exit code 2 is a blocking error — the tool call is stopped, unless the hook's JSON output explicitly overrides that outcome. Because the buggy script exits 2 and emits no JSON output to override it, the harmless command gets blocked exactly as if it had matched the dangerous pattern — a real, and instructive, consequence of the bug rather than a no-op.

The distractors don't match this behavior: exit codes 0 and 2 are not equivalent — one proceeds, the other blocks by default; Claude Code does consult the exit code itself (JSON on stdout refines the decision, it doesn't replace the exit code as the primary signal); and nothing in the hook mechanism auto-disables a hook after an unexpected result — a misbehaving hook keeps firing on every matching call until someone fixes or removes it.

Share this question

← Back to CLAUDE.md and Context Configuration practice

We use cookies for product analytics to improve OmniAtlas. See our Privacy Policy.