[macOS desktop] Continue in new worktree fails with EISDIR when dirty checkout contains an untracked directory
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
- In a Git repository, leave the working tree dirty and include an unignored nested directory among untracked files (for example,
.codex-worktrees/nested-task/). - In the ChatGPT macOS Codex UI, choose Continue this task in a new worktree.
- 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.
1 Comment
Confirmed on Windows in the current ChatGPT/Codex desktop worktree flow.
Environment:
OpenAI.Codex 26.818.3698.0Observed sequence (four occurrences):
The most deterministic Windows trigger is an untracked committed nested Git repository:
git initthere, add and commit one file in the nested repository.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 Nodefs.promises.cp(source, destination, { recursive: false/omitted, verbatimSymlinks: true })for each untracked entry. Passing the directory-shaped entry to that call reproducesERR_FS_EISDIR; the same fixture succeeds withrecursive: true.Additional Windows fixture results:
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.