[UX] Stop hook displays 'error' for intentional blocking behavior
Summary
When a Stop hook intentionally blocks Claude to provide guidance (exit 0 with "decision": "block"), the displayed message shows "Stop hook error:" even though no error occurred - the hook is working exactly as designed.
Current Behavior
Ran 1 stop hook
⎿ Stop hook error: Files were modified this turn. Use the Task tool to spawn 'memory-updater' agent...
The word "error" implies something went wrong, but this is the intended behavior - the hook successfully blocked Claude's stop and provided guidance for what to do next.
Expected Behavior
The message should not say "error" when the hook:
- Exits with code 0 (success)
- Returns valid JSON with
"decision": "block"and a"reason"
Suggested alternatives:
- "Stop hook:" (neutral)
- "Stop hook message:" (informational)
- "Stop hook blocked:" (accurate - describes what happened)
Reserve "Stop hook error:" for actual errors (exit code 2, invalid JSON, etc.).
Hook Implementation
# Exit 0 (implicit), returns valid JSON
output = {
"decision": "block",
"reason": "Files were modified this turn. Use the Task tool to spawn..."
}
print(json.dumps(output))
This follows the documented pattern for Stop hooks that intentionally block Claude to request follow-up actions.
Impact
- Users see "error" and think something is broken
- Developers may waste time debugging hooks that are working correctly
- Creates confusion about whether hooks are functioning as intended
Related Issues
- #10986 - Clarify blocking vs non-blocking hook status in hook messages
- #10463 - "Stop hook error" displayed despite hooks producing zero output
Environment
- Claude Code Version: 2.0.55
- Platform: Linux (WSL2)
Bump
Bump bump