UserPromptSubmit hook reports 'error' despite exit 0 and valid JSON output

Resolved 💬 3 comments Opened Apr 8, 2026 by Daeguk-Sun Closed Apr 8, 2026

Summary

UserPromptSubmit hook intermittently reports "hook error" to the user even when the hook script exits with code 0 and produces valid JSON on stdout. This is a false-positive error display — the hook output is actually accepted and applied correctly in some cases.

Reproduction

Hook config (~/.claude/settings.json):

{
  "hooks": {
    "UserPromptSubmit": [{
      "hooks": [{
        "type": "command",
        "command": "python3 /path/to/router.py auto 2>>/tmp/hook-stderr.log; exit 0",
        "timeout": 30
      }]
    }]
  }
}

What the hook does: Classifies user prompts via regex, outputs JSON with additionalContext:

{"hookSpecificOutput": {"additionalContext": "..."}}

Observed behavior:

  • Hook exits 0, outputs valid JSON (781 bytes), stderr is empty
  • User sees: ⎿ UserPromptSubmit hook error
  • Same hook, same config — sometimes shows hook success: OK, sometimes shows hook error
  • No pattern to which prompts trigger the error vs success

Diagnostic evidence (from custom logging added to the hook):

[22:39:43] FAST_CLASSIFY result=IMPLEMENTATION prompt='응 커밋 푸시 부탁해'
[22:39:43] INJECT(impl) issue=None prompt='응 커밋 푸시 부탁해'
[22:39:43] STDOUT len=781
  • stderr log file: empty (only the initialization header)
  • No uncaught exceptions logged
  • Script completes in <100ms (regex-only path, no subprocess calls)
  • Running the exact same prompt manually produces valid JSON + exit 0

What we ruled out:

  • Timeout (30s limit, script finishes in <100ms)
  • Non-zero exit code (forced ; exit 0 in command)
  • Invalid JSON (validated with json.dumps, logged output length)
  • stderr leakage (redirected to file, file is empty)
  • Uncaught exceptions (try/except wrapper with logging, no UNCAUGHT entries)
  • Large output (781 bytes)

Environment

  • macOS Darwin 24.6.0
  • Claude Code CLI (latest)
  • Python 3 (system)
  • Hook uses json.dumps() for output, sys.exit(0) for exit

Expected behavior

Hook should report "success" when script exits 0 with valid JSON output.

Actual behavior

Hook intermittently reports "error" with no diagnostic information, despite clean execution.

View original on GitHub ↗

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