Read/Edit deny non-ignored buildSrc/ source: "denied by your permission settings" with no deny rule (build-dir pattern over-match)
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
- In a Gradle project that has a
buildSrc/directory containing source (e.g.buildSrc/src/main/kotlin/.../Foo.kt), with nopermissions.denyrules anywhere. Read(orEdit)buildSrc/src/main/kotlin/.../Foo.kt.- →
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
denyrule configured,Read/Editinside 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: onlypermissions.defaultMode: acceptEdits - user
~/.claude/settings.local.json: absent - project
.claude/settings.json: absent - project
.claude/settings.local.json:allowlist only — nodeny, noask
Additional data points:
.gitignorecontainsbuild/, which (correctly) matchesapp/buildandbuildSrc/buildbut notbuildSrc/src(git check-ignoreconfirmsbuildSrc/srcis not ignored). YetbuildSrc/srcis still denied — so this is not driven by.gitignore.- Adding an explicit
permissions.allowentry forRead(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
allowcannot 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.