claude-code - 💡(How to fix) Fix [BUG] Stop hook exit code 2 downgraded to non-blocking when stderr contains unrelated 'no such file' [3 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#60490Fetched 2026-05-20 03:57:10
View on GitHub
Comments
3
Participants
3
Timeline
6
Reactions
1
Author
Timeline (top)
commented ×3labeled ×3

Error Message

Stop hook error: Hook script appears to be missing — "${CLAUDE_PLUGIN_ROOT}/hooks/python-pytest-passes.sh" exited 2 with: Error: pytest tests are failing! [... full pytest output including ...] FileNotFoundError: [Errno 2] No such file or directory: '/dev/uinput' [...] Please fix the failing tests before proceeding.. Treating as non-blocking instead of re-prompting. If this is a plugin hook, check the plugin install (run /plugin).

Root Cause

The hook in question is a pytest Stop hook from a plugin. It exits 2 when tests fail and writes the pytest output to stderr (as is conventional for error reporting). The false positive occurs because a containerized e2e test fails with a FileNotFoundError for /dev/uinput, and that traceback text in stderr matches the overly broad regex.

Code Example

if (status === 2
    && (event === "Stop" || event === "SubagentStop" || event === "TaskCompleted" || event === "TeammateIdle")
    && !stdout.trim()
    && /no such file|can't open/i.test(stderr)) {
  // Treats as non-blocking "hook script appears to be missing"
}

---

Stop hook error: Hook script appears to be missing — "${CLAUDE_PLUGIN_ROOT}/hooks/python-pytest-passes.sh" exited 2 with: Error: pytest tests are failing!
[... full pytest output including ...]
FileNotFoundError: [Errno 2] No such file or directory: '/dev/uinput'
[...]
Please fix the failing tests before proceeding.. Treating as non-blocking instead of re-prompting. If this is a plugin hook, check the plugin install (run /plugin).

---

#!/bin/bash
echo "FileNotFoundError: No such file or directory: '/dev/foo'" >&2
exit 2
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

A Stop hook that exits with code 2 (blocking) is silently downgraded to non-blocking when stderr happens to contain the text "no such file" — even when that text comes from test output, not from a missing hook script.

The hook runner has a special-case heuristic for Stop/SubagentStop/TaskCompleted/TeammateIdle events: if exit code is 2, stdout is empty, and stderr matches /no such file|can't open/i, it assumes the hook script itself is missing and treats the failure as non-blocking. The problem is the regex matches anywhere in stderr, so test output containing e.g. FileNotFoundError: [Errno 2] No such file or directory: '/dev/uinput' triggers the false positive.

The relevant code path (decompiled from v2.1.144 binary):

if (status === 2
    && (event === "Stop" || event === "SubagentStop" || event === "TaskCompleted" || event === "TeammateIdle")
    && !stdout.trim()
    && /no such file|can't open/i.test(stderr)) {
  // Treats as non-blocking "hook script appears to be missing"
}

What Should Happen?

Exit code 2 from a Stop hook should block, as documented. The "missing script" heuristic should not match arbitrary content in stderr — it should be scoped to the hook script path itself (e.g., matching only the command that was invoked, not the full stderr output).

Error Messages/Logs

Stop hook error: Hook script appears to be missing — "${CLAUDE_PLUGIN_ROOT}/hooks/python-pytest-passes.sh" exited 2 with: Error: pytest tests are failing!
[... full pytest output including ...]
FileNotFoundError: [Errno 2] No such file or directory: '/dev/uinput'
[...]
Please fix the failing tests before proceeding.. Treating as non-blocking instead of re-prompting. If this is a plugin hook, check the plugin install (run /plugin).

Steps to Reproduce

  1. Create a Stop hook that runs a test suite and exits with code 2 on failure, writing output to stderr (stdout empty)
  2. Have one of the tests fail with a FileNotFoundError or any error containing "no such file" in the traceback
  3. Observe that the hook is treated as non-blocking ("Hook script appears to be missing") instead of blocking the stop

Minimal reproduction — a Stop hook script that does:

#!/bin/bash
echo "FileNotFoundError: No such file or directory: '/dev/foo'" >&2
exit 2

This will be treated as non-blocking despite exit code 2.

Claude Model

Opus

Is this a regression?

I don't know

Claude Code Version

2.1.144 (Claude Code)

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Xterm

Additional Information

The hook in question is a pytest Stop hook from a plugin. It exits 2 when tests fail and writes the pytest output to stderr (as is conventional for error reporting). The false positive occurs because a containerized e2e test fails with a FileNotFoundError for /dev/uinput, and that traceback text in stderr matches the overly broad regex.

Suggested fix: anchor the regex to the hook command/path itself rather than matching anywhere in stderr. For example, check if stderr starts with or only contains a shell "no such file" error for the hook script path, rather than searching the full stderr output.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING