[BUG]

Status Fixed / completed
Reported on v2.1.29
Maintainer reply ✓ Yes — claude[bot]
Activity 8 comments · opened Feb 2, 2026 · closed Apr 23, 2026
💡 Likely answer: A maintainer (claude[bot], contributor) responded on this thread — see the highlighted reply below.

Preflight Checklist

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

What's Wrong?

Agent-type hooks in PreToolUse fail to execute with the error: Failed to run: Messages are required for agent hooks. This is a bug.

When configuring an agent hook to run before Bash commands (specifically to check documentation before git push), the hook is matched correctly but fails to execute because it doesn't receive the required messages/context.

What Should Happen?

Agent hooks configured in PreToolUse should receive the conversation context and execute successfully, allowing the agent to analyze the command and return {ok: true} or {ok: false, reason: "..."}.

Error Messages/Logs

2026-02-02T20:00:39.160Z [DEBUG] Getting matching hook commands for PreToolUse with query: Bash
2026-02-02T20:00:39.160Z [DEBUG] Found 1 hook matchers in settings
2026-02-02T20:00:39.160Z [DEBUG] Matched 1 unique hooks for query "Bash" (1 before deduplication)
2026-02-02T20:00:39.161Z [DEBUG] Hook PreToolUse:Bash (PreToolUse) error:
Failed to run: Messages are required for agent hooks. This is a bug.

Steps to Reproduce

  1. Create .claude/settings.json with an agent hook:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "agent",
            "prompt": "Check if this is a git push command. If not, return {\"ok\": true}. If it is, verify documentation is up to date.",
            "timeout": 90
          }
        ]
      }
    ]
  }
}
  1. Run any Bash command through Claude Code (e.g., git push origin master)
  2. Observe the hook error in debug logs

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.29

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code integrated terminal

Additional Information

The hook matcher works correctly (logs show it matched 1 hook for "Bash"), but the agent execution fails because messages aren't being passed to the agent context. Command-type hooks may work as a workaround, but agent-type hooks appear fundamentally broken for PreToolUse.

View original on GitHub ↗

8 Comments

dpowley · 6 months ago

We are running into the same issue, but on PostToolUse.

Version: 2.1.37, macOS, Anthropic API

Error: Failed to run: Messages are required for agent hooks. This is a bug.

DeanFromLondon · 6 months ago

Also hitting this with PermissionRequest hooks using type: "agent".

Use case: I have an Opus-based "Permissions Gatekeeper" agent configured to evaluate Bash commands for safety — classifying them as SAFE (auto-approve) or RISKY (auto-block) before execution. This would allow running in acceptEdits mode while still catching destructive commands like rm -rf, git reset --hard, git push --force to main, DROP TABLE, etc.

Configuration (in ~/.claude/settings.json):

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "agent",
            "prompt": "Classify this Bash command as SAFE or RISKY...",
            "model": "opus",
            "timeout": 30,
            "statusMessage": "Gatekeeper review..."
          }
        ]
      }
    ]
  }
}

What happens: The hook is completely bypassed — the standard permission dialog appears instead of the agent evaluation. The statusMessage never shows.

Key observations:

  • The agent prompt works perfectly when invoked manually via the Task tool
  • type: "command" hooks on other events (Stop, SessionStart) work fine
  • Only type: "agent" hooks appear broken

Originally filed as #23370 (auto-closed as duplicate of this issue).

DeanFromLondon · 6 months ago

Root Cause Identified: Settings serialization drops prompt field

After further investigation with backup history analysis, I've identified the root cause of this bug:

Claude Code silently drops the prompt field from type: "agent" hooks when re-serializing settings.json.

Reproduction Steps

  1. Add a PermissionRequest hook with type: "agent" and a prompt field to ~/.claude/settings.json
  2. Run Claude Code and approve any new Bash command (which adds it to permissions.allow)
  3. Check settings.json — the prompt field is gone, while all other fields (type, timeout, model, statusMessage) are preserved

Evidence from Backup History

I have automated daily backups of settings.json. Timeline:

| Date | prompt field | What changed |
|------|----------------|--------------|
| Feb 4 | ✅ Present | Initial setup |
| Feb 8 | ❌ Gone | Permissions list modified in same write |
| Feb 9 | ✅ Present | Manually restored |
| Feb 11-12 | ✅ Present | No settings changes |
| Feb 15 | ❌ Gone | skipDangerousModePermissionPrompt added + permissions cleaned |

Diagnostic Output

When the prompt field is missing, Claude Code shows this validation error on startup:

Invalid Settings
/Users/dean/.claude/settings.json
 └ hooks
   └ PermissionRequest
     └ 0
       └ hooks
         └ 0
           └ prompt: Expected string, but received undefined

Impact

This explains why:

  • Agent hooks work initially but then mysteriously stop
  • The error says "Messages are required for agent hooks" — because the prompt IS missing (dropped by Claude Code itself)
  • Manual restoration gets overwritten on next settings change
  • There's no reliable workaround

Expected Behavior

Claude Code should round-trip all hook handler fields when re-serializing settings.json, including the prompt field.

---

Version: Claude Code 2.1.42 (native install), macOS

weiT1993 · 6 months ago
## Root Cause Identified: Settings serialization drops prompt field After further investigation with backup history analysis, I've identified the root cause of this bug: Claude Code silently drops the prompt field from type: "agent" hooks when re-serializing settings.json. ### Reproduction Steps 1. Add a PermissionRequest hook with type: "agent" and a prompt field to ~/.claude/settings.json 2. Run Claude Code and approve any new Bash command (which adds it to permissions.allow) 3. Check settings.json — the prompt field is gone, while all other fields (type, timeout, model, statusMessage) are preserved ### Evidence from Backup History I have automated daily backups of settings.json. Timeline: Date prompt field What changed Feb 4 ✅ Present Initial setup Feb 8 ❌ Gone Permissions list modified in same write Feb 9 ✅ Present Manually restored Feb 11-12 ✅ Present No settings changes Feb 15 ❌ Gone skipDangerousModePermissionPrompt added + permissions cleaned ### Diagnostic Output When the prompt field is missing, Claude Code shows this validation error on startup: `` Invalid Settings /Users/dean/.claude/settings.json └ hooks └ PermissionRequest └ 0 └ hooks └ 0 └ prompt: Expected string, but received undefined ` ### Impact This explains why: * Agent hooks work initially but then mysteriously stop * The error says "Messages are required for agent hooks" — because the prompt IS missing (dropped by Claude Code itself) * Manual restoration gets overwritten on next settings change * There's no reliable workaround ### Expected Behavior Claude Code should round-trip **all** hook handler fields when re-serializing settings.json, including the prompt` field. Version: Claude Code 2.1.42 (native install), macOS

I found that when Claude Code needs to make changes to settings.json, such as add permission mode, it drops the prompt field.

But that is not the only issue. I manually added all the settings required into settings.json so that re-serialization does not get triggered and prompt is preserved. But agent type hooks do not pass messages to the agent hook runner and it silently fails.

chase-crumbaugh · 5 months ago

Also facing this

claude[bot] contributor · 4 months ago

This issue was fixed as of version 2.1.118.

bretr · 4 months ago

Still reproducing on Claude Code 2.1.111 (macOS 25.2.0), 3 months after this was closed as stale.

Error (from transcript hook_non_blocking_error attachment):

{
  "stderr": "Failed to run: Messages are required for agent hooks. This is a bug.",
  "stdout": "",
  "exitCode": 1,
  "command": "<statusMessage>",
  "durationMs": 1
}

durationMs: 1 confirms it fails at config-dispatch time, before any model call.

Minimal repro in .claude/settings.local.json:

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "agent",
        "if": "Bash(git commit*)",
        "prompt": "Summarize the commit that just ran.",
        "timeout": 60
      }]
    }]
  }
}

Then run any git commit. The agent hook crashes instantly while the sibling type: command hook fires fine.

Contradiction: the settings validator requires prompt (string) and rejects messages with additionalProperties: false. The runtime rejects what the validator accepts — there's no schema that satisfies both.

~12 new duplicates have been filed and closed since this issue went stale. Worth reopening.

github-actions[bot] · 3 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.