Trust dialog suppressed by ancestor trust while permission loading exact-matches the workspace key — subfolder permissions silently dropped with no interactive remedy
Versions affected: introduced in 2.1.193; still present in 2.1.197 (latest) and 2.1.198 (next).
Repro
- Trust a plain (non-git) parent directory by running
claudethere and accepting the trust dialog. - In a subfolder (non-git, or its own git root), add
.claude/settings.jsonwithpermissions.allowentries. - Run
claudein the subfolder → stderr shows "Ignoring N permissions.allow entries… this workspace has not been trusted" — and no trust dialog ever appears.
Root cause
Two trust checks disagree:
checkHasTrustDialogAccepted(gates the TrustDialog at startup) walks up ancestor directories in~/.claude.jsonprojects— any trusted ancestor suppresses the dialog.isWorkspacePersistedTrusted(gates permission-rule loading) exact-matches the workspace key:gitRoot(cwd) ?? resolve(cwd)— no ancestor walk.
In the mismatch state, project permissions.allow rules and additionalDirectories are dropped, and the warning tells the user to "run Claude Code interactively here once and accept the trust dialog" — which the ancestor-walking check guarantees can never appear. Only subfolders outside the trusted parent's git repo are affected; same-repo subfolders resolve to the trusted git root and work correctly.
Impact
Reported by an enterprise customer (who independently root-caused it via strings on the binary). Managed fleets on ≥2.1.196 hit this on any non-git multi-project directory layout. The only remedy is a manual ~/.claude.json edit: projects["<exact path printed in the warning>"].hasTrustDialogAccepted: true.
Suggested direction
Align the dialog gate to the same exact-match workspace key so the dialog is shown in the subfolder. The reverse fix (honoring ancestor trust in permission loading) would weaken the trust model, so exact-match on both sides looks like the safe alignment.
Related: #72507, #72610 (same symptom family — trust dialog unreachable while permissions are gated — different triggers), #71562.
Showing cached comments. Read the full discussion on GitHub ↗
5 Comments
Found 2 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Not a duplicate of #72547 or #67319 — same symptom family (trust dialog unreachable while permissions are gated), different mechanism. #72547 is the session being misdetected as non-interactive and #67319 is VS Code extension-specific. This issue reproduces in a plain interactive CLI session: the dialog gate (checkHasTrustDialogAccepted) walks up ancestor directories and finds the trusted parent, so it intentionally skips the dialog, while permission loading (isWorkspacePersistedTrusted) exact-matches the cwd/git-root key and gates the rules. Fixing either of the other two would not resolve this one.
Hit this exact mismatch today on 2.1.197 (Linux/WSL2), with an extra twist worth documenting: the trusted ancestor in my case is
/itself.Setup:
~/.claude.jsoncontainsprojects["/"].hasTrustDialogAccepted: truefrom a session run in/months ago (long before 2.1.193). Since/is an ancestor of everything, the ancestor-walking dialog gate suppresses the trust dialog in every directory on the machine, while the exact-match permission gate drops rules everywhere that lacks its own key.Symptom: launching
claudeinteractively in$HOMEprintsIgnoring 39 permissions.allow entries from .claude/settings.local.json: this workspace has not been trusted...and no dialog ever appears. The untracked-in-git fallback for local settings doesn't rescue it either:$HOMEis not a git repo, sogit ls-files --error-unmatch .claude/settings.local.jsonexits 128 and the file is treated as unverifiable.Both remedies suggested by the warning fail:
projects["$HOME"].hasTrustDialogAccepted: truein~/.claude.json" — the edit is silently reverted if any Claude session is running (config rewritten from the app's write path; observed the flag flip back tofalsewithin a minute). Nothing warns you that all sessions must be closed first.Workaround that worked: with all sessions exited, delete the
projects["/"]entry, relaunch — the dialog fires again and accepting it sets the exact-match key.Agree with @markso-ops this is not a duplicate of #72547 / #67319 — plain interactive CLI, session correctly detected as interactive, no VS Code involved.
🤖 Comment co-authored-by: Claude Fable 5
The safest fix is to define one canonical workspace identity function and use it for both trust UI and rule loading. Two independently implemented trust predicates will keep drifting. I would also make the failure closed and actionable: if permission rules are dropped, show the exact canonical key and expose a supported trust command rather than requiring direct state-file edits. Regression coverage should include plain parent/subfolder, nested git roots, symlinks, case differences, and a trusted ancestor with an untrusted child.
this bit me hard on a couple projects, and it ended up being due to them being on mapped network drives, and claude's path not matching gits project path I believe - git project root was the network drive d:/etc/blah, while claude's was the share's IP / UNC path eg //192.168.1.2/etc/blah - it told me to paste this sorry for the slop but it seems accurate byeee
Mapped network drive + UNC git root: trust key can never match, so the workaround is mandatory (v2.1.209)
Confirming this on VS Code extension 2.1.209 (issue reports 2.1.193–2.1.198, so the affected range extends further than currently documented), and adding a variant I don't see mentioned yet: when the repo is opened via a mapped drive letter but git reports the root as UNC, the trust key can never be written correctly by any UI flow.
Why this variant is worse than the general case
Per the mechanism described in this issue,
isWorkspacePersistedTrustedexact-matches ongitRoot(cwd) ?? resolve(cwd). On a mapped network drive those two disagree in form, not just in value:The gate looks up the UNC string;
.claude.jsonis keyed on the drive letter; the lookup misses; all project-scopepermissions.allowrules are silently dropped. No warning is logged.The critical consequence: accepting a trust dialog would not fix this even if one appeared, because the dialog writes the key for the workspace path (
d:/…), not the git root (//NAS/…). The two gates disagree about identity, not just about ancestry. Combined with #34913 (the VS Code extension never shows the CLI's trust prompt), there is no in-product path to a working state — the manual~/.claude.jsonedit isn't a convenience workaround here, it's the only option.Symptom (diagnostic fingerprint)
A very specific split that makes this easy to misdiagnose for hours:
| Rule location | Trust-gated? | Result |
|---|---|---|
|
~/.claude/settings.json(user scope) | No | Never prompts ||
.claude/settings.json(project) | Yes | Always prompts ||
.claude/settings.local.json(project, if committed) | Yes | Always prompts |In my case every
mcp__<server>__*tool prompted despite all 50 tools being listed explicitly by name in.claude/settings.json, while Bash/Read/Grep/WebFetch never prompted — purely because those happened to be allowed in user scope. That split is the tell. It sends you off editing project settings syntax, which cannot possibly work, and.claude/settings.local.jsongets caught by the same gate the moment it's committed to git.Fix that works
Add
hasTrustDialogAccepted: trueunder the UNC-form key in~/.claude.json— byte-for-byte whatgit rev-parse --show-toplevelreturns:Verified working: MCP tools that prompted on every call now run with no prompt, and the hand-written keys survive a reload (the harness does not prune or rewrite them). I added the backslash variant and the
d:/key as belt-and-braces, but the forward-slash UNC key is the one that matchesgit rev-parseoutput.⚠️ Edit this file with node, not PowerShell.
ConvertTo-Jsonin PS 5.1 defaults to-Depth 2and will silently mangle a large nested config. I round-trippedJSON.parse→JSON.stringify(_, null, 2)and confirmed byte-identical output before writing, then re-validated with an independent parser.Suggested resolutions, in order of preference