Hooks format migration: confusing error messages and undocumented format change

Resolved 💬 2 comments Opened Jan 9, 2026 by mmarschall Closed Jan 9, 2026

Summary

When migrating settings.json hooks from an older format, the error messages are confusing and don't clearly explain what the new format should be.

Old format (no longer works)

{
  "hooks": {
    "Stop": [
      {
        "type": "command",
        "command": "echo done"
      }
    ]
  }
}

Error received

Settings Error

/home/devuser/.claude/settings.json
 └ hooks
   └ Stop
     └ 0
       └ hooks: Expected array, but received undefined

Hooks use a new format with matchers. Example: {"PostToolUse": [{"matcher": {"tools":
["BashTool"]}, "hooks": [{"type": "command", "command": "echo Done"}]}]}

The problem

  1. The error says hooks: Expected array, but received undefined but doesn't explain that the structure changed from flat to nested
  2. The example shows "matcher": {"tools": ["BashTool"]} (an object), but for Stop hooks the matcher should be an empty string ""
  3. When I tried "matcher": {} (empty object), got a different error: matcher: Expected string, but received object

Correct format (discovered through trial and error)

{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "echo done"
          }
        ]
      }
    ]
  }
}

Suggestions

  1. Improve error message to show the exact expected structure for the hook type being configured
  2. Provide different examples for different hook types (PostToolUse vs Stop) since they have different matcher requirements
  3. Consider a migration tool or clearer migration guide for the hooks format change

Environment

  • Claude Code CLI
  • Running in Docker container

View original on GitHub ↗

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