[UX] Distinguish 'Stop hook execution error' from 'Stop hook objection' when hook returns ok:false

Resolved 💬 1 comment Opened May 25, 2026 by faizkhairi Closed Jun 3, 2026

Summary

When a Stop hook executes successfully and returns {"ok": false, "reason": "..."}, Claude Code surfaces the message as "Stop hook error:" in the transcript. This conflates two distinct outcomes:

  1. Hook execution error — the hook script crashed, timed out, or returned malformed JSON
  2. Hook objection — the hook ran fine and reported a policy violation in the model's response

Both currently render under the same "error" label, which is misleading. Case #2 is the intended success path for a review-style hook.

Repro

Configure a Stop hook that returns {"ok": false, "reason": "..."}:

{
  "hooks": {
    "Stop": [{
      "hooks": [{
        "type": "prompt",
        "prompt": "Respond with {\"ok\": false, \"reason\": \"test\"}",
        "model": "claude-haiku-4-5-20251001"
      }]
    }]
  }
}

Trigger any assistant turn. Observe:

Ran 1 stop hook (ctrl+o to expand)
  ⎿  Stop hook error: ... : test

Expected

Two distinct labels:

  • "Stop hook error:" — execution failure (non-zero exit, timeout, malformed output)
  • "Stop hook violation:" (or "Stop hook objection") — successful run, ok: false returned

Why this matters

Review/verification hooks (security checks, CLAUDE.md policy enforcement, verify-after-complete patterns) are a common Stop hook use case. Their purpose is to return ok: false when they catch something. Labeling that path as "error" makes correct hook behavior look like a bug to users and conflates real script failures with policy reports — both in the UI and in any log scraping users do.

Environment

  • Claude Code CLI
  • macOS (Darwin 25.3.0) reported, but affects all Stop hook types (prompt and command) regardless of OS

Credit

Originally reported by @harixth at https://github.com/faizkhairi/claude-code-blueprint/issues/3 — filing upstream here because the fix belongs in the CLI, not in a downstream template repo.

View original on GitHub ↗

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