Skip to content

Codex App create_thread worktree rows fail with 'Worktree init failed' and no recoverable error #28204

Open

Description

@johnsilvavlogs

What version of the Codex App are you using?

Codex App 26.609.41114 build 3888

Bundled CLI: codex-cli 0.140.0-alpha.2

Global CLI on the same machine: codex-cli 0.135.0

What platform is your computer?

macOS 26.3 build 25D125

What issue are you seeing?

A parent/orchestrator Codex thread attempted to create two worktree-backed project threads through the create_thread tool. The tool returned only pending worktree IDs, and the Codex sidebar then showed both child rows as:

Worktree init failed

The parent thread had no returned threadId, no follow-up API to inspect/cancel/resolve the pending worktree, and no useful error message explaining why init failed.

Observed pending IDs from the tool results:

{"pendingWorktreeId":"local:8afc1d65-0aeb-450b-9ec7-6f76b68bba58"}
{"pendingWorktreeId":"local:85344054-5e7f-49c2-a751-65872c865ceb"}

What steps can reproduce the bug?

From a visible Codex manager/orchestrator thread in a local Git project, call create_thread twice with a project worktree target similar to:

{
  "target": {
    "type": "project",
    "projectId": "/path/to/local/git/project",
    "environment": {
      "type": "worktree",
      "startingState": { "type": "working-tree" }
    }
  },
  "thinking": "xhigh",
  "prompt": "You are a managed direct-report thread..."
}

Actual result:

  1. create_thread returns only pendingWorktreeId.
  2. The sidebar creates rows for the pending workers.
  3. Within about one minute, both rows display Worktree init failed.
  4. The parent/orchestrator cannot inspect the failed pending worktree, cannot retrieve a failure reason, cannot send a correction, and cannot cancel or clean it up through the tool surface.

Diagnostic evidence from the local machine

After the failure:

  • No matching new directories existed under ~/.codex/worktrees for the two pending IDs.
  • No normal threads rows were created for the failed pending worktrees in ~/.codex/sqlite/state_5.sqlite.
  • Searching the live ~/.codex/sqlite/logs_2.sqlite around the failure time for the pending IDs, worktree, and failed did not expose an actionable worktree-init error.
  • git worktree add --detach HEAD /tmp/... from the same repo succeeded and was removed cleanly, so the base Git repository and filesystem permissions appear healthy.
  • The app-server was running from the bundled CLI and the Codex app was otherwise responsive.

Expected behavior

At minimum, failed pending worktree initialization should surface an actionable error to the parent/orchestrator and the UI.

One or more of these would make the workflow recoverable:

  1. create_thread returns a stable reserved threadId plus pendingWorktreeId, even before init completes.
  2. A pending-worktree API exists, for example read_pending_worktree(pendingWorktreeId), cancel_pending_worktree(pendingWorktreeId), and resolve_pending_worktree(pendingWorktreeId).
  3. The failed sidebar row can expose the exact failing command/stderr or a structured failure reason.
  4. list_threads or another tool can search pending/failed worktree rows by pendingWorktreeId.
  5. Failed pending worktree rows are cleanup-able through the tool surface.

Why this matters

This blocks visible manager/worker workflows in Codex Desktop. An orchestrator can request independent worker threads, but if Codex worktree setup fails, the parent is left with only a non-addressable pendingWorktreeId and a sidebar row saying Worktree init failed.

The user-facing failure is especially rough because the app visibly creates failed worker rows but the agent has no programmatic recovery path or error details.

Related issues

This issue is specifically about the pending worktree reaching a visible Worktree init failed state with no actionable error, no persisted thread, and no tool-level recovery path.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    app-serverIssues involving app server protocol or interfaces
    tool-callsIssues related to tool calling
    on Jun 14, 2026
  2. github-actions commented on Jun 14, 2026

    @github-actions
    Contributor

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

    Powered by Codex Action

  3. johannesdehaan commented on Jul 22, 2026

    @johannesdehaan

    I can add a fully diagnosed reproduction of this same failure and recovery gap.

    Environment

    • Codex Desktop 26.715.52143, build 5591
    • Bundled codex-cli 0.145.0-alpha.18
    • macOS 26.5.2 / arm64

    Repository layout and reproduction

    The saved Codex project pointed at an umbrella directory:

    workspace/             # saved project root; not itself inside Git
      repo/                 # bare Git common-dir
      linked-worktree-a/
      linked-worktree-b/
      ...
    

    Two worktree-backed create_thread calls returned only:

    client-new-thread:997da77f-f8a7-47fa-9a8c-f77158be7e8e
    client-new-thread:e627de81-af95-4ae0-8e07-85fcc301063d
    

    Both later showed Worktree init failed, never received a regular threadId, and never appeared in list_threads.

    Confirmed root cause

    Codex resolves the source repository by running:

    git rev-parse --show-toplevel
    

    with the saved project root as sourceWorkspaceRoot. At the umbrella root this exits 128:

    fatal: not a git repository (or any of the parent directories): .git
    

    Git does not search child directories, so the bare common-dir and valid linked worktrees below the umbrella are irrelevant to this probe.

    Inspection of the bundled Desktop implementation confirms this exact chain:

    1. repository resolution runs rev-parse --show-toplevel;
    2. the “not a git repository” result resolves to no repository;
    3. managed worktree creation throws exactly Not a git repository;
    4. this occurs before path allocation, git worktree add, branch selection, hooks, setup scripts, permissions, or worktree-count handling.

    The provisioner catch path stores the message only on the in-memory pending-worktree entry and desktop notification. Persistent Codex logs contain the successful create_thread tool response returning the client ID, but not the later provisioning failure. Once the pending UI entry disappears, there is no queryable status or error keyed by that ID.

    Verified workaround and fix

    Local mode continued to work.

    Registering a fully independent, ordinary non-bare clone as a separate saved project fixed Worktree mode. A controlled validation then showed:

    • pending client ID promoted to a real threadId;
    • managed cwd under $CODEX_HOME/worktrees;
    • --is-inside-work-tree=true;
    • --is-bare-repository=false;
    • detached HEAD at the expected commit;
    • clean status;
    • archive cleanup removed the managed worktree.

    Using a linked checkout whose common-dir was the bare repository exposed a separate shared-config mutation bug, now reported as #34828.

    Suggested improvements

    1. Preflight sourceWorkspaceRoot before accepting or queueing Worktree mode and return a synchronous, actionable error.
    2. Persist pending/failed provisioning status and sanitized stderr keyed by the returned client ID.
    3. Expose read/cancel/retry operations for pending worktrees, as discussed in Codex App create_thread returns pendingWorktreeId without an addressable threadId #26861.
    4. For umbrella projects, allow an explicit child Git root or remembered default repository, as discussed in Codex App: support parent workspaces containing multiple Git repositories #26338.

    The reliable workaround is Local mode or a saved project rooted in an independent ordinary non-bare clone.

  4. jnyross commented on Aug 9, 2026

    @jnyross

    Additional reproduction from jnyross/codex-graph Lisbon v4 dogfood (Codex Desktop, 2026-08-09).

    Three create_thread calls for read-only research workers used environment: { type: "worktree" } on a saved Codex project. Each returned only:

    {"clientThreadId":"client-new-thread:<uuid>","hostId":"local"}

    The orchestrator polled list_threads for 120s and never observed the pending rows. The terminal is mac-vm-harness--codexgraph-test/candidates/frozen-lisbon-v4/terminal-lisbon-v4.json (blocked, all handles in pending_setup, unresolved risk "Required research starts failed: N2A, N2B, N2C").

    This is the same silent pending-resolution class: the parent has no threadId, no error, and no pending-worktree API to recover. The skill fix (PR #14, v0.4.5) now preflights isGitRepository === true before any worktree create and degrades a single repository writer to a root-orchestrator write, which avoids the silent class for read-only workers.

    See also #26861 for the related addressability gap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingtool-callsIssues related to tool calling

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions