[Bug] Async PostToolUse hook systemMessage not delivered to model context
Bug Description
Title: Async PostToolUse hook systemMessage never delivered to model context
Version: Claude Code 2.1.50
Description:
Async PostToolUse hooks that output JSON with systemMessage on stdout (exit 0) never deliver the message to the model's context. The hook runs successfully, debug output confirms completion, but the
systemMessage is silently dropped.
We followed the exact example from the Claude Code documentation ("Run tests after file changes" in the Hooks reference), which shows:
echo "{\"systemMessage\": \"Tests failed after editing $FILE_PATH: $RESULT\"}"
Steps to reproduce:
- Create .claude/hooks/check.sh:
```
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
RESULT=$(pnpm typecheck 2>&1)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "{\"systemMessage\": \"Typecheck passed after editing $FILE_PATH\"}"
else
echo "{\"systemMessage\": \"Typecheck failed after editing $FILE_PATH: $RESULT\"}"
fi
2. Configure .claude/settings.json:
```
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check.sh",
"async": true,
"timeout": 30
}
]
}
]
}
}
- Start a session, have Claude edit a .ts file with a type error
- Send a follow-up message (to trigger the "next conversation turn" delivery)
Expected: Model receives the systemMessage on the next turn.
Actual: Debug output shows Async hook PostToolUse completed but no systemMessage appears in the model's context. Multiple session restarts confirmed.
Workaround: Use synchronous (non-async) hooks with exit code 2 + stderr output. This correctly feeds errors to the model.
Environment Info
- Platform: darwin
- Terminal: WarpTerminal
- Version: 2.1.50
- Feedback ID: 1d48f1ef-21e4-442f-b1ad-91bec73375a8
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗