Skip to content

Fix scoped-filesystem access-denied errors in codex builds - #3865

Merged
Mpdreamz merged 2 commits into
mainfrom
fix/codex-scoped-filesystem
Aug 14, 2026
Merged

Fix scoped-filesystem access-denied errors in codex builds#3865
Mpdreamz merged 2 commits into
mainfrom
fix/codex-scoped-filesystem

Conversation

@Mpdreamz

@Mpdreamz Mpdreamz commented Aug 13, 2026

Copy link
Copy Markdown
Member

Why

The codex build command failed. It showed Access denied errors. 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:

.artifacts/codex/docs/
├── r/
│   └── my-repo/              <- one repo's own folder: r/my-repo/
│       ├── index.html
│       └── config/
├── r/my-repo.md              <- LlmMarkdownExporter writes here, ONE LEVEL UP from my-repo/
├── _static/                  <- CodexGenerator writes here, at the TOP folder
├── index.html                <- CodexGenerator writes the home page here
└── redirects.json

Two parts of the code write files outside a single repo's own folder:

  • LlmMarkdownExporter writes a file next to the repo folder, one level up.
  • CodexGenerator writes 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 denied error.

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

  • Build the project. Result: no errors.
  • Run all unit tests. Result: all tests pass.
  • Run the code format checker. Result: no problems found.
  • Run a real codex build with several repos. Check the output files: sibling .md files, the _static folder, redirects.json, and index.html. Result: all files are in the correct place. No Access denied errors.

Mpdreamz and others added 2 commits August 13, 2026 21:04
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>
@Mpdreamz
Mpdreamz requested a review from a team as a code owner August 13, 2026 19:06
@Mpdreamz
Mpdreamz requested a review from reakaleek August 13, 2026 19:06
@Mpdreamz Mpdreamz added the bug label Aug 13, 2026
@Mpdreamz
Mpdreamz merged commit 89a3d52 into main Aug 14, 2026
26 checks passed
@Mpdreamz
Mpdreamz deleted the fix/codex-scoped-filesystem branch August 14, 2026 09:46
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants