Codex turn-diff tree refs break libgit2-based Git clients

Open 💬 9 comments Opened Jun 15, 2026 by elachlan

What version of the Codex App are you using (From “About Codex” dialog)?

Version 26.609.41114 • Released 13 June 2026

What subscription do you have?

ChatGPT Plus

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What issue are you seeing?

After using Codex in a Git repository, libgit2-based clients can fail when browsing refs.

In my case, TortoiseGit's "Browse References" failed with:

Get refs failed: libgit2 returned: the requested type does not match the type in the ODB

The repo contained many local Codex refs under:

.git/refs/codex/turn-diffs/

Running:

git for-each-ref --format="%(refname) %(objectname) %(objecttype)" refs/codex/turn-diffs

showed that these refs point directly to Git tree objects, for example:

refs/codex/turn-diffs/checkpoints/... d1385fb55aef5f5e121dda8f44de1f9c6b9720b3 tree
refs/codex/turn-diffs/captures/.../base 2033976581293cb7624fbd566bed1154125af248 tree

Normal branch and remote refs pointed to commits.
git fsck --full --no-reflogs did not report repository corruption. Deleting the local Codex turn-diff refs fixed the issue:

git for-each-ref --format="%(refname)" refs/codex/turn-diffs |
  ForEach-Object { git update-ref -d $_ }

What steps can reproduce the bug?

general codex usage against a git repo.

What is the expected behavior?

Codex scratch/checkpoint data should not create ordinary refs that Git GUI clients enumerate as normal refs, especially refs pointing directly to tree objects.

Additional information

View original on GitHub ↗

9 Comments

wgu9 · 1 month ago

This looks like a real Git object/ref contract issue rather than repository corruption.

The important clue is that git for-each-ref reports refs under refs/codex/turn-diffs/... whose target object type is tree. Core Git plumbing allows refs to point at non-commit objects, so git fsck can stay clean, but many Git clients and libraries treat ordinary refs under refs/* as branch/tag-like refs and try to peel or inspect them as commits. A libgit2-based client failing with “requested type does not match the type in the ODB” is consistent with enumerating a normal ref that unexpectedly points directly to a tree object.

I did not find the refs/codex/turn-diffs writer in the open-source Rust checkout I have, so this may live in the Desktop/app turn-diff layer. But the fix direction seems independent of platform:

  • do not store scratch turn-diff/checkpoint refs as ordinary enumerable refs that point directly to tree objects; or
  • if refs are required, point them to commit objects whose tree is the desired snapshot; or
  • store the mapping outside normal refs, for example under app state / notes / an internal namespace that libgit2 GUI ref browsers will not enumerate as branch-like refs.

A good regression check would create a repository after a Codex turn-diff capture and assert:

git for-each-ref --format='%(refname) %(objecttype)' refs/codex/turn-diffs

never reports tree for refs that remain in the user's working repository. If tree snapshots need to exist, they should not be exposed as ordinary refs that third-party Git clients browse.

The user workaround using git update-ref -d is consistent with this diagnosis: deleting those local scratch refs removes the libgit2 enumeration failure without touching normal branches, remotes, or objects.

Per the contribution policy I am not opening a PR, but I wanted to separate the likely Git-ref shape issue from actual repo corruption.

buybackoff · 1 month ago

I have faced this issue in a sandboxed WSL, on fresh plain Debian 13 with basic essential dev tools. I could not syncronize with a remote.

git pull --tags remotename branchname
fatal: bad object refs/codex/turn-diffs/checkpoints/b35651126431a5c32e302a7a6b051c9c30732d57957d873cde5846753047aef0/b5eb4d411c507ccf180cf1a9bc95036051090e00fb7dc9f2f75c0b20566a23cd/1781518144817/8b097b47-a8b7-4530-bfb1-8470fbd9acc2
error: github.com:orgname/reponame.git did not send all necessary objects

Deleting refs/codex/ fixed the issue.

It's so bad the Codex can ever write to .git, and even worse do so silently. I will have to complicate the setup with worktrees and I cannot trust Codex not to break a repo again. It should be one untouchable folder that requires its own very explicit permission to even read it.

elachlan · 1 month ago

@etraut-openai this now seems worse, as it shows Codex refs can break normal Git CLI operations too, not just GUI clients.

buybackoff · 1 month ago

@elachlan I was using VS Code remote and its UI.

elachlan · 1 month ago

@buybackoff You might need to report your issue on the git issue tracker.

wthee00 · 1 month ago

I’m seeing the same issue with SourceTree.

Environment:

  • Codex IDE extension version: 26.609.30741
  • Subscription: ChatGPT Plus
  • IDE: VS Code
  • Platform: Microsoft Windows NT 10.0.26220.0 x64
  • Git client affected: SourceTree

What happens:

After starting a Codex chat in VS Code, Codex creates refs under:

refs/codex/turn-diffs/checkpoints/...

After that, SourceTree stops showing my local branches. Sometimes fetch also fails with errors like:

fatal: bad object refs/codex/...
error: did not send all necessary objects

Running this command fixes SourceTree immediately:

git for-each-ref --format='delete %(refname)' refs/codex | git update-ref --stdin

After deleting those refs, SourceTree shows local branches again and fetch works.

So this appears to affect SourceTree as well, not only TortoiseGit/libgit2 reference browsing.

[https://github.com/openai/codex/issues/28847](url)

elachlan · 1 month ago

@wthee00 I suggest you report your issue to SourceTree. My understanding is that tools are allowed to created refs. It just that most git clients don't handle them robustly.

elachlan · 1 month ago

This has now been fixed in TortoiseGit v2.19.0 and no longer causes crashes. Other git clients will need to improve their tree handling.

lg320531124 · 29 days ago

Cross-referencing #29388 which documents the disk space bomb from the same refs/codex/turn-diffs/ mechanism. In my case, 102 GB of orphan blob objects accumulated from checkpoint tree snapshots, bringing a 5.7 GB project to 140 GB. The root cause is write_tree() in baseline.rs writing a blob for every file in the project on each checkpoint, with no gc/prune.