Read/Edit deny non-ignored buildSrc/ source: "denied by your permission settings" with no deny rule (build-dir pattern over-match)

Open 💬 0 comments Opened Jul 15, 2026 by MarcinGawel-TomTom

Summary

Read and Edit refuse every file under a Gradle project's buildSrc/ source directory with:

File is in a directory that is denied by your permission settings.

…even though no deny rule exists in any settings scope, and buildSrc/src/** is not git-ignored. The same error also fires for real build/ output dirs (e.g. app/build/...). This looks like a non-segment-anchored build-directory pattern (a default ignore, or a //-prefix over-match in the spirit of #25175) that catches the legitimate buildSrc/ source tree, not just build/ output.

Environment

  • Claude Code: 2.1.210
  • OS: macOS 26.5.2 (Darwin 25.5.0, arm64)
  • Project: a large Gradle/Android monorepo with a buildSrc/ module
  • permissions.defaultMode: acceptEdits

Reproduce

  1. In a Gradle project that has a buildSrc/ directory containing source (e.g. buildSrc/src/main/kotlin/.../Foo.kt), with no permissions.deny rules anywhere.
  2. Read (or Edit) buildSrc/src/main/kotlin/.../Foo.kt.
  3. Error: File is in a directory that is denied by your permission settings.

Also reproduces for a non-existent path under any build/ dir (so the check is a path-pattern match evaluated before file existence), e.g. app/build/outputs/nonexistent.txt.

Expected

  • buildSrc/ is first-class Gradle source, not build output — it should be readable/editable like any other source dir.
  • With no deny rule configured, Read/Edit inside the working directory should not be denied at all (per the permissions docs, read-only tools work within the working dir without explicit allow rules).

Actual

Both buildSrc/** and build/** are hard-denied with the "denied by your permission settings" message.

Investigation / evidence

Verified there is no deny (and no ask) rule in any scope:

  • managed-settings (/Library/Application Support/ClaudeCode/…, /etc/claude-code/…): absent
  • user ~/.claude/settings.json: only permissions.defaultMode: acceptEdits
  • user ~/.claude/settings.local.json: absent
  • project .claude/settings.json: absent
  • project .claude/settings.local.json: allow list only — no deny, no ask

Additional data points:

  • .gitignore contains build/, which (correctly) matches app/build and buildSrc/build but not buildSrc/src (git check-ignore confirms buildSrc/src is not ignored). Yet buildSrc/src is still denied — so this is not driven by .gitignore.
  • Adding an explicit permissions.allow entry for Read(buildSrc/**) / Edit(buildSrc/**) (both absolute //… and relative forms, at project and project-local scope) does not lift the block.
  • The block distinguishes itself from the auto-mode classifier: the classifier emits "denied by the Claude Code auto mode classifier", whereas this emits "denied by your permission settings" — i.e. the deterministic path-rule engine, not a semantic classifier. It's identical every time and fires pre-existence.
  • The settings do contain some auto-generated //-prefixed allow rules (e.g. Read(//Users/<me>/repo/<proj>/buildSrc/**)), which is why #25175 (the //bin/** over-match producing this exact error string) seems related.

Likely related

  • #25175 — Edit/Write deny pattern '//bin/**' incorrectly matches project-relative bin/ — same error string, same class of //-prefix / non-segment-anchored over-match.
  • #14311 — project-level allow cannot override higher-precedence path denies (explains why adding allow rules did nothing).

Question for maintainers

Is there an undocumented default ignore for build directories applied to Read/Edit? If so, (a) it should be segment-anchored so it matches build/ but not buildSrc/, and (b) there should be a documented way to override it. If instead this is a //-prefix / glob over-match bug, it's the same root cause as #25175 extended to build*.

Workaround

Read/edit buildSrc files via a subprocess that isn't a recognized file-command (e.g. a python3 script using open()), which bypasses the path check.

View original on GitHub ↗