[macOS desktop] Continue in new worktree fails with EISDIR when dirty checkout contains an untracked directory

Open 💬 1 comment Opened Aug 9, 2026 by growthpigs

Surface

Observed in ChatGPT for macOS's embedded Codex worktree flow, not via the Codex CLI.

  • ChatGPT: 26.803.41515
  • Codex Framework: 151.0.7922.76

If this repository is not the correct tracker for the desktop worktree orchestrator, please route or transfer this report.

Reproduction

  1. In a Git repository, leave the working tree dirty and include an unignored nested directory among untracked files (for example, .codex-worktrees/nested-task/).
  2. In the ChatGPT macOS Codex UI, choose Continue this task in a new worktree.
  3. Inspect the creation log.

Observed

The operation aborts while copying untracked files:

[info] Starting worktree creation
[info] Applying working tree diff to new worktree
[info] Copying untracked files to new worktree
[stderr] Path is a directory: cp returned EISDIR

No new worktree/task is created.

Expected

The continuation flow should either copy untracked directories recursively (preserving their hierarchy) or intentionally exclude generated worktree directories. It should not attempt to treat an untracked directory as a single file and abort.

Impact and workaround

In the affected checkout, .codex-worktrees/ contained nested generated worktrees. Adding .codex-worktrees/ to Git's global excludes file prevents that generated state from entering the untracked-file handoff. That is only a workaround: any arbitrary, unignored directory can still trigger the underlying failure.

View original on GitHub ↗

1 Comment

Anson7055 · 3 days ago

Confirmed on Windows in the current ChatGPT/Codex desktop worktree flow.

Environment:

  • Windows desktop App package/version: OpenAI.Codex 26.818.3698.0
  • Repository on a local NTFS volume
  • The failing path is a normal directory, not a junction or symbolic link

Observed sequence (four occurrences):

Preparing worktree at detached HEAD
Applying working tree diff
Copying untracked files
Path is a directory: cp returned EISDIR

The most deterministic Windows trigger is an untracked committed nested Git repository:

  1. Create and commit a baseline file in an outer repository.
  2. Create a directory inside it, run git init there, add and commit one file in the nested repository.
  3. Leave the nested repository untracked by the outer repository.
  4. Start a new desktop task using the outer repository's working tree and managed-worktree isolation.

The outer command git ls-files --others --exclude-standard -z -- returns the committed nested repository as one directory-shaped entry. Inspection of the installed desktop bundle shows that the local copy host reaches Node fs.promises.cp(source, destination, { recursive: false/omitted, verbatimSymlinks: true }) for each untracked entry. Passing the directory-shaped entry to that call reproduces ERR_FS_EISDIR; the same fixture succeeds with recursive: true.

Additional Windows fixture results:

  • ordinary nested untracked files: clear (Git enumerates the files)
  • committed nested repository: reproduces the directory-shaped blocker
  • committed nested repository with spaces in its path: same blocker
  • failed desktop attempts: no new native task ID, Git worktree registration, or managed-worktree child directory remained after cleanup

This supports the original report's conclusion that the issue is not specific to generated worktree directories. A robust fix should either enumerate directory contents before copying or enable recursive directory copying with an explicit symlink/reparse-point policy. A regression suite should cover ordinary directories, nested repositories, paths with spaces, symlinks/reparse points, and failure cleanup.

I intentionally omitted full logs, local usernames, repository names, and task database data. I can provide a smaller synthetic fixture if maintainers need one.