Skip to content

[Bug]: Failed bootstrap leaves new-thread draft pinned to a deleted thread ID #4647

Description

@Tyler-Petrov

Before submitting

  • I searched existing issues and did not find an open issue specifically tracking the persisted stale draft ID after bootstrap cleanup.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web, apps/server

Steps to reproduce

  1. Add a project that is a valid Git repository but has no commits (HEAD is unborn).
  2. Configure new threads to use worktree mode.
  3. Open a new draft, enter a prompt, and send it.
  4. thread.created succeeds, then git worktree add fails because there is no commit from which to create the worktree.
  5. Bootstrap cleanup emits thread.deleted for the provisional thread.
  6. Retry sending the prompt, restart T3 Code, or reopen the project's new-thread draft.

The no-commit worktree failure is already tracked in #2148. This issue tracks the separate persistent state left behind after that or another bootstrap failure.

Expected behavior

When bootstrap cleanup deletes a provisional thread, the client should invalidate or regenerate the draft's thread ID. Retrying should use a fresh aggregate ID, preserve the prompt, and either retry bootstrap or return the original actionable error.

Actual behavior

The composer draft remains persisted in t3code:composer-drafts:v1 and continues to map the project draft to the deleted thread ID. Every retry attempts thread.create with that tombstoned aggregate ID and fails with:

Orchestration command invariant failed (thread.create):
Thread '<thread-id>' already exists and cannot be created twice.

Restarting T3 Code does not fix the problem because the mapping survives in local storage. Changing defaultThreadEnvMode to local also does not repair an existing draft because its stored threadId remains unchanged.

The event and trace sequence in this reproduction was:

thread.created
GitCommandError: git worktree add failed
thread.deleted (29 ms after creation)
thread.create retries with the same thread ID
OrchestrationCommandInvariantError: already exists and cannot be created twice

The relevant persisted draft state remained equivalent to:

{
  "threadId": "<deleted-thread-id>",
  "envMode": "worktree",
  "worktreePath": null,
  "promotedTo": null
}

The server correctly retains the original thread.created and thread.deleted events, so the deleted aggregate ID cannot be reused. The client draft must therefore stop reusing it after cleanup.

Impact

Blocks work completely

The affected project appears permanently locked to the deleted ID. New-thread retries and application restarts continue to produce the invariant error.

Version or commit

T3 Code Nightly 0.0.29-nightly.20260725.899

Environment

Linux, Electron 41.5.0, repository with an unborn master branch and uncommitted files.

Logs or stack traces

OrchestrationCommandInvariantError: Orchestration command invariant failed (thread.create): Thread '<thread-id>' already exists and cannot be created twice.
    at requireThreadAbsent
    at decideOrchestrationCommand
    at orchestration.command.thread.create

Workaround

Manually repair the persisted composer draft by preserving its prompt and draft ID, assigning a fresh thread UUID, switching it to local mode, and reloading T3 Code.

Related issues: #2148, #378, #624.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions