[BUG] Notification hook receives phantom `permission_prompt` events with no visible permission dialog
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?
The Notification hook with permission_prompt matcher fires even when no permission dialog is displayed to the user. This creates phantom notification events that cannot be correlated to any visible UI.
Observed behavior:
PreToolUse:AskUserQuestionfires at time TNotification:permission_promptfires at T+6 seconds- No permission dialog appears - only the AskUserQuestion UI is visible
- User receives two notifications when only one is meaningful
This occurs consistently (~6 second gap) when working from the user's home directory (/Users/user), but does NOT reproduce when working from project directories.
What Should Happen?
Notification:permission_prompt should only fire when Claude Code actually displays a permission prompt to the user. If no permission dialog is shown, no permission_prompt notification event should be generated.
Error Messages/Logs
Debug logging captured both events with timestamps:
15:10:04.887 | event=question | project=user | cwd=/Users/user
15:10:11.310 | event=permission | project=user | cwd=/Users/user
- `question` = PreToolUse:AskUserQuestion hook (legitimate - dialog shown)
- `permission` = Notification:permission_prompt hook (PHANTOM - no dialog shown)
- **6.4 second gap** between events
Steps to Reproduce
- Configure a Notification hook with
permission_promptmatcher in~/.claude/settings.json:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"command": "python3 /path/to/notify.py --event permission"
}
]
}
]
}
}
- Also configure a PreToolUse hook for AskUserQuestion:
{
"hooks": {
"PreToolUse": [
{
"matcher": "AskUserQuestion",
"hooks": [
{
"type": "command",
"command": "python3 /path/to/notify.py --event question"
}
]
}
]
}
}
- Set permission mode to "accept edits" (not "don't ask" - the bug doesn't reproduce when AskUserQuestion is blocked)
- Start Claude Code from the home directory:
cd ~ && claude
- Ask Claude to do something that triggers an AskUserQuestion (e.g., "use AskUserQuestion to test me on tequila")
- Observe: Two notifications fire - first for the question, then ~6 seconds later for a phantom permission_prompt with no visible permission dialog
- Compare: Run the same task from a project subdirectory - only one notification fires (the question)
Reproduction Matrix
| Condition | Phantom appears? |
|-----------|------------------|
| Home dir (~) + AskUserQuestion shows dialog | YES |
| Home dir + AskUserQuestion blocked (dontAsk mode) | NO |
| Project dir + AskUserQuestion shows dialog | NO |
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.0.76
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Hook Configuration Context
The notification hook is designed to alert users when:
Stop- Task completeNotification:permission_prompt- Permission requiredPreToolUse:AskUserQuestion- Question askedPreToolUse:ExitPlanMode- Plan ready
The phantom permission_prompt events make the permission notification unreliable - users receive "Authorization required" notifications when no authorization is actually needed.
Root Cause Hypothesis
The ~6 second delay suggests this may be related to internal timeout or retry logic. Claude Code appears to generate a spurious Notification:permission_prompt event when AskUserQuestion is used from non-project directories.
Workaround
A marker-based suppression system could filter phantom permission_prompt events that follow AskUserQuestion within a short window (similar to the workaround for the Stop hook firing multiple times during git workflows - see issue #15250).
However, this workaround should not be necessary - permission_prompt events should only fire when a permission dialog is actually displayed.
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗