VS Code Codex diff fails to load full file content

Open 💬 8 comments Opened May 20, 2026 by Redbird10
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the IDE extension are you using?

26.513.21555

What subscription do you have?

Plus

Which IDE are you using?

VS Code

What platform is your computer?

Darwin 25.4.0 arm64 arm (Mac OS)

What issue are you seeing?

In the VS Code Codex diff view, a simple change to a tracked file fails to load the full file content.

The UI shows:

Full file content failed to load

with a Retry button. Clicking Retry does not resolve the issue.

What steps can reproduce the bug?

Feedback ID: 019e45e7-3599-7a50-b966-f908ecaebd35

  1. Open a git repository in VS Code with the Codex extension enabled.
  2. Ask the Codex extension to modify a tracked file. In my repro, the file was robots.txt.
  3. Codex made a simple one-line insertion:

``diff
# https://www.robotstxt.org/robotstxt.html
+# Site crawler access rules
User-agent: *
Disallow:
``

  1. Open the Codex diff view for that change by clicking the review button in the chat.
  2. Observe that the diff view shows the file header, the full-content load failure, and only a few diff lines:

``text
robots.txt
Full file content failed to load
<a few diff lines>
``

  1. Click the Retry button.
  2. The same failure remains.

What is the expected behavior?

_No response_

Additional information

Diagnostic Notes From Local Instrumentation

The following section is based on local instrumentation added by Codex itself while debugging. Please treat it as reference material, not as a definitive fix proposal.

After adding temporary logging to the local installed extension bundle, the failing full-content load appeared to come from the diff webview calling:

git.request({
  method: "cat-file",
  params: {
    cwd,
    path,
    oid,
    fallbackToDisk,
    operationSource: "thread_diff"
  }
})

The debug output showed that the diff metadata used an absolute path:

diff.name: /private/tmp/codex-review-repro/robots.txt
workspaceRoot: /private/tmp/codex-review-repro

But the cat-file request appeared to expect a repository-relative path:

robots.txt

With the absolute path, both sides initially failed:

{
  oldResult: {
    type: "error",
    error: { type: "not-found" }
  },
  newResult: {
    type: "error",
    error: { type: "not-found" }
  }
}

After locally normalizing the path from:

/private/tmp/codex-review-repro/robots.txt

to:

robots.txt

the new side loaded successfully from disk, but the old side still failed:

{
  oldResult: {
    type: "error",
    error: { type: "not-found" }
  },
  newResult: {
    type: "success",
    lines: [
      "# https://www.robotstxt.org/robotstxt.html\n",
      "# Site crawler access rules\n",
      "User-agent: *\n",
      "Disallow:\n"
    ]
  },
  nextFallbackToDisk: false
}

The old side appeared to fail because the diff metadata did not include prevObjectId, and the request effectively had:

oid: null
fallbackToDisk: false

The extension-side cat-file handler appears to return not-found for that combination.

As a local experiment only, I patched the installed extension to resolve the old side with:

git rev-parse HEAD:<path>

and then read that blob with git cat-file. With that local experiment, the full-content load succeeded and the Retry button disappeared.

Possible Cause

Based on the above local investigation, the failure may involve two related issues:

  1. The partial diff metadata may provide an absolute file path where the full-content loader expects a repo-relative path.
  2. The old-side full-content loader may not have a fallback when prevObjectId is missing and fallbackToDisk is false.

Again, this diagnosis was produced from local instrumentation and should be treated as a debugging lead rather than a confirmed root cause.

View original on GitHub ↗

8 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #23326

Powered by Codex Action

Redbird10 · 2 months ago
Potential duplicates detected. Please review them and close your issue if it is a duplicate. * Undo failed in latest extension (26.513) #23326 _Powered by Codex Action_

Undo and reapply seems to be working on my side.
And this issue only happens in the VS Code extension. The same conversation, when opened in the Mac OS Codex app, is working correctly without that issue.

RainbowPopsicle · 1 month ago

I encountered the same problem on win11.

YuHan-233 · 1 month ago

I also encountered the same problem in the Codex application of Windows 11. The issue doesn't occur when I disable the "Load Complete File" option. Could it be because the context of the complete file is too lengthy?

guojinjim · 1 month ago

I hit what looks like the same underlying bug in Codex Desktop, with a worktree/cwd mismatch variant.

Environment:

  • Codex Desktop / app-server thread from cli_version: 0.133.0
  • macOS Darwin arm64
  • The UI was localized, but the visible error was the equivalent of Full file content failed to load, with a retry button.

Anonymized repro shape:

Thread cwd:
  /Users/example/src/project/service

Actual file modified by the agent:
  /Users/example/src/project/.worktree/feature-branch/service/path/to/file_test.go

The patch/diff itself rendered correctly because the patch_apply_end event had the absolute changed-file path and unified diff. However, when the diff viewer tried to expand/load the full file content for the changed file, it showed the full-content load failure.

In this case the target file still existed on disk and was readable after the failure:

/Users/example/src/project/.worktree/feature-branch/service/path/to/file_test.go

So this does not look like a missing-file or permission issue. It looks consistent with the diagnosis above: the diff metadata/full-content loader does not consistently handle absolute paths, or it resolves/validates the file against the thread cwd/workspace root instead of the actual worktree path recorded in the patch event.

Expected behavior:

  • If a patch event records an absolute path in a different git worktree than the thread's original cwd, the diff viewer should still load the full file content from that recorded path, or from the correct worktree/repo-relative path.
  • If loading fails, the UI should expose the underlying reason/path used for fs/readFile/cat-file instead of only showing the generic full-content failure message.

This seems related to #23709 rather than a separate issue, so adding it here as another data point.

dann-it · 28 days ago

I have the same with my VS Code (running on Windows 11). I see for every changed file this message:

<img width="508" height="285" alt="Image" src="https://github.com/user-attachments/assets/8b6b555a-d5ca-4234-af25-fa2628701af8" />

jeonsavvy · 26 days ago

I reproduced this on Windows Desktop and found a second, deterministic failure mode that is independent of file size or encoding.

Environment

  • Codex Desktop 26.616.81150
  • Windows 11
  • Tracked UTF-8 Markdown file, ~7 KB
  • The file was readable from PowerShell and the repository was healthy (git status, git cat-file, and object checks all behaved normally)

Root cause observed

The turn diff contains blob-looking object IDs that are calculated from the captured before/after contents, but those blobs are not necessarily present in the repository object database.

Current TurnDiffTracker::render_diff() computes both IDs with git_blob_oid(...) and writes them into the unified diff's index line:

https://github.com/openai/codex/blob/a0d5fd772e076851e6f17d1e821c797154e2916f/codex-rs/core/src/turn_diff_tracker.rs#L309-L355

The desktop full-content loader then interprets those IDs as resolvable Git objects and requests git cat-file with operationSource: "thread_diff". For newly generated, uncommitted content, the computed SHA-1 identifies what the blob would be, but TurnDiffTracker has not written that blob into Git's object database.

I verified the sequence directly in the affected repository:

  1. Apply a Codex patch to a tracked file.
  2. Compute the worktree content with git hash-object <file>.
  3. git cat-file -e <computed-id>^{blob} exits 128 because the object is absent.
  4. Open the review: the partial hunk renders, but full-content expansion shows Full file content failed to load.
  5. Retry repeats the same lookup and fails again.
  6. Commit the file. Git writes the exact same blob ID; git cat-file -e now exits 0.

This explains the persistent Retry behavior and why the problem can affect small, valid files. It also complements the absolute-path/worktree observations already reported here: path normalization can be correct and the lookup can still fail because a synthesized object ID is not an ODB-backed object.

Suggested invariant

A blob ID emitted in turn-diff metadata should only be used for cat-file when its provenance guarantees that it is readable from the target repository. Captured-content hashes and repository object IDs are currently indistinguishable to the client.

Potential fixes, in preference order:

  1. Expose the captured before/after snapshots through an app-server-owned lookup and let the review surface load full content from that snapshot source.
  2. Add provenance to distinguish captured-content IDs from ODB-backed IDs, with worktree fallback for the current side after not-found.
  3. Writing every transient snapshot into the user's Git ODB would make cat-file work, but seems less desirable because it mutates the repository object store and leaves unreachable blobs.

For the old side, falling back to HEAD:<path> is not fully correct because the patch baseline may itself contain uncommitted edits. The captured baseline held by TurnDiffTracker is the authoritative source.

Regression coverage I would propose

  • Start with a tracked file whose baseline differs from HEAD.
  • Apply a Codex patch without committing.
  • Confirm neither synthesized content hash needs to exist in the Git ODB.
  • Assert that the review/full-content source returns the exact captured baseline and final content.
  • Cover a nested cwd / alternate worktree path.
  • Assert Retry does not repeat a permanently impossible cat-file lookup.

I can prepare the focused test and implementation if this direction matches the intended desktop/app-server architecture. Since external PRs require an explicit maintainer invitation, please let me know whether you would prefer an app-server snapshot lookup or another approach.

Harry813 · 10 days ago

I reproduced this on current Codex Desktop for macOS, and the failure still occurs in an aggregate-root + nested-worktree layout.

Environment

  • Codex Desktop: 26.707.31428 (build 5059)
  • Session CLI: 0.144.0-alpha.4
  • macOS, Darwin arm64
  • Thread cwd is an aggregate project directory, not itself a Git repository
  • The changed file belongs to a Git worktree nested below that aggregate directory

Anonymized layout:

Thread cwd:
/Users/example/project

Actual repository/worktree:
/Users/example/project/.worktrees/feature

Changed file shown by Review:
.worktrees/feature/.gitignore

Observed behavior

The partial hunk renders, but expanding it shows:

Full file content failed to load

The file still exists and is normally readable. The Git baseline can also be read when the correct worktree root is used:

git -C /Users/example/project/.worktrees/feature show :.gitignore
# succeeds

The equivalent lookup from the thread/aggregate cwd fails:

git -C /Users/example/project show :.worktrees/feature/.gitignore
fatal: not a git repository (or any of the parent directories): .git

A useful additional detail: the affected Codex turn did not modify any files. The Review sidebar discovered pre-existing dirty files from the nested worktree. This means diff discovery can identify a nested worktree under an aggregate project, while the full-content loader still appears to retain the thread cwd instead of the owning repository/worktree root.

Expected behavior

For each discovered diff, full-content loading should carry the owning Git repository/worktree root and use a repository-relative path for the before/index side. Retry should not repeat a lookup from a known non-Git aggregate cwd.

Disabling “Load full files” remains a workaround, but the full context should load correctly for nested repositories/worktrees.