[Critical data loss][Windows Desktop] Archiving a managed worktree follows a Junction and deletes files in the external target

Open 💬 2 comments Opened Jul 22, 2026 by tyzhr2026-cell
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Codex Desktop Windows Junction Archive Data-Loss Reproduction

Result

Reproduced (1/1) on 2026-07-22.

Archiving a Codex-managed Git worktree task recursively removed a file from the real directory referenced by a Windows Junction inside that worktree.

The junction target root remained present, but its contents were deleted. This is data loss outside the managed worktree.

Environment

  • Codex Desktop package: 26.715.8383.0
  • Codex Desktop app-server client version recorded during thread/archive: 26.715.61943
  • Codex command runner: 0.145.0-alpha.27
  • Windows: Microsoft Windows NT 10.0.26200.0
  • PowerShell: 7.6.0
  • Git: 2.53.0.windows.2
  • Main project: D:\fun
  • Seed commit: 35b5dc925f7bf9a09e50c4941e919484b2eb0973

Controlled layout

Real target outside the managed worktree:

D:\fun\_codex_archive_junction_repro\real-target\KEEP_ME.txt

Codex-managed worktree and junction:

C:\Users\TR\.codex\worktrees\5b7d\fun
└── junction-repro-root
    └── linked-real-target  [Windows Junction]
        -> D:\fun\_codex_archive_junction_repro\real-target

Test task ID:

019f88cf-2296-7a23-a135-142a1d3cbdf5

Pre-archive evidence

  • Worktree existed and was registered by git worktree list --porcelain.
  • Link attributes: Directory, ReparsePoint.
  • Link type: Junction.
  • Link target: D:\fun\_codex_archive_junction_repro\real-target.
  • KEEP_ME.txt existed both directly and through the junction.
  • SHA256, direct and through the junction:
926F86C88812313491127A5F5DEFF956801A4BFCEFDC961A1BC5E4D1B6DC5B1F

The test task reported REPRO_READY only after all checks passed.

Trigger

The test task was archived using Codex Desktop's task archive operation. Local logging confirms a thread/archive RPC for the exact test task at Unix timestamp 1784706783.

Post-archive evidence

Checked at 2026-07-22T15:53:16+08:00, roughly two seconds after archive completion:

| Check | Result |
|---|---|
| Managed worktree Git registration | Removed |
| Junction path | Removed |
| Worktree directory | Remained, empty |
| Real target directory | Remained, empty |
| KEEP_ME.txt in real target | Deleted |
| Main-project sibling files | Unaffected |
| Archived rollout | Present |

Archived rollout:

C:\Users\TR\.codex\archived_sessions\rollout-2026-07-22T15-51-50-019f88cf-2296-7a23-a135-142a1d3cbdf5.jsonl

Control experiment

Archiving and restoring the ordinary local task rooted at D:\fun did not remove the same target or junction. The destructive behavior appeared only when archiving a Codex-managed Git worktree task, which exercises worktree cleanup.

Expected behavior

Worktree cleanup must treat Windows reparse points, Junctions, and symbolic links as leaf entries: remove the link itself without traversing into or deleting anything in the target.

Actual behavior and likely fault boundary

The observable behavior is consistent with cleanup traversing the Junction target, deleting its children, and only then removing the Junction. This is an inference from the before/after state; the available local log records the archive RPC but does not expose the Desktop cleanup implementation call.

Severity and mitigation

Severity: critical data loss. A worktree can legitimately contain Junctions to dependency caches, source trees, build artifacts, or other user directories outside the worktree.

Until fixed:

  1. Do not archive Codex-managed worktree tasks while their worktrees contain Windows Junctions or directory symlinks.
  2. Remove the link entry safely and verify the real target before archiving.
  3. Prefer copying disposable data into a worktree rather than linking valuable directories into it.
  4. Back up any external target before testing archive behavior.

Related upstream material

  • OpenAI Codex issue #18509: <https://github.com/openai/codex/issues/18509>
  • Codex app-server archive protocol: <https://github.com/openai/codex/blob/main/codex-rs/app-server/README.md>

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 1 month ago

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

  • #33507

Powered by Codex Action

Jethro71717 · 1 day ago

Corroborating report: I hit the same Windows data-loss class on 2026-08-26, but the trigger was automatic managed-worktree retention cleanup rather than manually archiving a task.

Environment

  • Codex Desktop package: 26.820.7780.0 (x64)
  • Bundled Codex: 0.150.0-alpha.8
  • Windows

Observed trigger and evidence

  • Creating two managed worktrees raised the managed-worktree count to 19.
  • Desktop logs planned automatic cleanup with keepCount=15 and selected two older worktrees.
  • Those older worktrees contained top-level Windows Junctions into the Local checkout: both linked node_modules; one also linked .venv.
  • Cleanup invoked git worktree remove --force. One removal failed quickly on an inaccessible .pytest_cache; the other ran for 10.214 seconds and then failed. The cleanup worker subsequently logged the removals as successful.
  • During that exact cleanup window, the Local checkout's node_modules and .venv were emptied. Because the Local node_modules contained normal npm workspace Junctions back to two tracked workspace application directories, 270 tracked files in those directories were also deleted.
  • Git history and the index remained intact, so the tracked files were recoverable with git restore; the dependency environments had to be rebuilt.
  • No user task or newly launched job issued a delete command. The deletion began before either new job's first read-only command.

This is an inference from the Desktop/worker logs, filesystem timestamps, and the verified Junction graph, but the timing and affected paths line up exactly with automatic cleanup.

The same leaf-entry rule described in this issue needs to cover automatic retention cleanup, not only explicit archive actions. Suggested defense in depth:

  1. Inspect reparse points without dereferencing them and unlink only the Junction itself.
  2. Resolve each cleanup candidate and fail closed if any descendant resolves outside the managed worktree.
  3. Never report cleanup success after git worktree remove --force fails.
  4. Treat nested workspace links inside a linked dependency tree as another containment boundary.

This also appears related to #35745. I can provide sanitized log excerpts if useful.