Denial messages don't say which permission rule or settings file fired

Status Open
Reported on v2.1.233
Maintainer reply None cached
Activity 0 comments · opened Aug 16, 2026

Denial messages don't say which permission rule or settings file fired

Summary

When a permissions.deny rule blocks a tool call, the error shown is generic — e.g.
"Permission ... has been denied" or "File is in a directory that is denied by your
permission settings." — with no indication of which rule matched or which settings file
(project .claude/settings.json, user ~/.claude/settings.json, settings.local.json,
managed settings) it came from.

This makes debugging permission behavior much harder than it needs to be, especially when
multiple settings files can define overlapping/interacting rules. In our case, tracking down
an unexpected allow/deny outcome took significantly longer than necessary because we had to
manually add/remove candidate rules and re-test rather than reading the answer off the error
itself.

Request: include the matched rule string and its source file in the denial message, e.g.
Blocked by deny rule "Read(./.env.*)" from ~/.claude/settings.json.

Environment

  • Claude Code version: 2.1.233
  • OS: macOS 26.5.2 (build 25F84)

Supplementary observation: Write(path) rule-validity warning is invisible in interactive mode

Separately, we noticed that claude -p (print/headless mode) prints a startup validation
warning for Write(path)-style deny rules:

Permission deny rule (<settings file>): Write(./.env) is not matched by file permission checks
— only Edit(path) rules are. Use Edit(./.env) instead (Edit rules cover all file-editing tools).

This warning never appeared in our normal interactive sessions, even though the same
Write(...) rules were present in the loaded settings the whole time. If this validation is
useful (it told us something we didn't know — that Write(path) rules are silently never
enforced), it would be more useful surfaced in interactive mode too, not just -p.

View original on GitHub ↗