Fix scoped-filesystem access-denied errors in codex builds - #3865
Merged
Conversation
The disjoint-root filters in CheckoutsFileSystem, DocumentationFileSystem, AssemblyWriteFileSystem, and DocumentationWriteFileSystem dropped AppData outright whenever it nested with the checkout/output root either way. That's wrong when AppData is actually the wider path (e.g. a codex checkout cloned under AppData/codex/clone/<repo>): keeping only the narrower checkout root silently hid sibling AppData directories like config-runtime that reads still need, causing "Access denied" failures. The new AddDisjointRoot helper keeps whichever of the two paths is the outer one instead of just skipping the overlap. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…docset's
Per-docset write scopes in codex builds are narrowly scoped to r/{repoName}/,
but two codex-wide writers need to write outside that: LlmMarkdownExporter
writes a sibling r/{repoName}.md one level up, and CodexGenerator writes
landing/group pages and _static assets to the codex root. Both were resolving
their filesystem from the per-docset BuildContext, so once write scopes were
narrowed they hit "Access denied".
LlmMarkdownExporter now takes an optional DocumentationWriteFileSystem,
constructed by CodexBuildService with the codex-wide CodexContext.WriteFileSystem
when composing exporters for a codex build. CodexGenerator already receives
outputDirectory (backed by the codex-wide filesystem) but was shadowing it with
the narrower BuildContext.WriteFileSystem -- a one-line fix.
BuildDocumentationSet (and its exporter composition) also moved from the
general-purpose IsolatedBuildService into CodexBuildService, since it was
codex-only logic that doesn't belong on a service other build paths depend on.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
theletterf
approved these changes
Aug 14, 2026
yetanothertw
pushed a commit
that referenced
this pull request
Aug 14, 2026
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The
codex buildcommand failed. It showedAccess deniederrors. It failed even when the file paths were correct. Two separate problems caused this.What
Problem 1: the code threw away the wrong folder
The code builds a list of folders that a build may read or write. Some folders sit inside other folders. Old code kept only one folder in each pair and threw away the other one. The code always kept the inner (smaller) folder.
This was wrong in one case. A codex checkout can sit inside the app's data folder. In this case, the app's data folder is the correct folder to keep. The old code threw it away instead. This removed access to other files inside the app's data folder, like
config-runtime. Those files were still needed.The fix adds a new helper,
AddDisjointRoot. It keeps the outer (bigger) folder, not the inner folder.Problem 2: two writers used the wrong file system scope
A codex build makes one output folder per repository. This diagram shows the folder layout:
Two parts of the code write files outside a single repo's own folder:
LlmMarkdownExporterwrites a file next to the repo folder, one level up.CodexGeneratorwrites shared files. Examples: the home page and the static assets folder. These files go in the top folder, not in one repo's folder.Both parts used the file system scope for one repo's folder. This scope was too narrow. It did not cover the folder one level up, or the top folder. This caused the
Access deniederror.The fix gives both parts the correct, wider file system scope. This scope covers the whole codex output tree. Other build types (isolated builds, assembler builds) do not use this wider scope. They keep their normal, narrower scope.
Small cleanup
One method,
BuildDocumentationSet, was only used by codex builds. It lived in a shared file used by other build types too. The fix moves this method into the codex-specific file. This makes the code easier to read. It does not change behavior for other build types.Test plan
.mdfiles, the_staticfolder,redirects.json, andindex.html. Result: all files are in the correct place. NoAccess deniederrors.