Skip to content

[Bug]: Forking a Claude thread fails after its project's workspace root changes #22796

Closed

Description

@urjitc

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Create a project at /work/app and run at least one turn in a Claude thread.
  2. Move the repository to /work/app/platform and point the project at it (t3_project_update with the new workspaceRoot, which records a project.meta-updated event).
  3. Continue the thread. This still works.
  4. Fork the thread from any response and send a message in the fork.

Expected behavior

The fork starts from the parent's Claude session, the same way continuing the parent still does.

Actual behavior

The fork's turn fails to start with "Provider turn failed to start: Claude Agent SDK query failed." The server trace shows:

ProviderAdapterForkThreadError: Failed to fork claudeAgent provider thread …
  [cause]: ClaudeAgentSdkQueryRunnerError: Claude Agent SDK query failed.
    [cause]: Error: Session <id> not found in project directory for /work/app/platform

Claude files a transcript under the directory the session started in (~/.claude/projects/-work-app/<id>.jsonl). forkThread passes the thread's current cwd as dir (ClaudeAdapterV2.ts, forkOptions). With dir, the SDK only checks that directory's project folder and its git worktrees, so it never finds -work-app. Without dir, forkSession searches every project, which is how resume finds the same session.

The subagent launch lookup (subagentLaunchToolUseId, called with dir: runtimePolicy.cwd) has the same cwd pinning after a root change. Open PR #17596 is rewriting that call for custom Claude homes, so I left it out of the fix for this report.

Not a duplicate of #18260 (custom homePath, fixed in #18662): there the transcript was in a different Claude home. Here it is in the right home, but under an earlier project directory.

Impact

Major degradation or frequent failure

Version or commit

0.1.2-nightly.20261021.3457 (desktop, nightly)

Environment

macOS (Darwin 27), T3 Code desktop nightly, Claude Agent SDK 0.3.276, Claude provider on the default home.

Workaround

Symlink the transcript into the current directory's project folder: ln -s ~/.claude/projects/<old-slug>/<id>.jsonl ~/.claude/projects/<new-slug>/.

Activity

  1. urjitc commented on Oct 25, 2026

    @urjitc
    Author

    Nice ty

  2. bignosecss commented on Nov 10, 2026

    @bignosecss

    Confirming the same failure on 0.1.8 with a worktree-based variant of this repro.

    Environment: T3 Code desktop (Beta), server 0.1.8; macOS client driving a remote Ubuntu environment over SSH; Claude Code CLI 2.1.321 through the claudeAgent provider (custom model). Not a custom Claude home.

    Repro:

    1. A long-running Claude thread was created inside a git worktree of the project (<repo>/worktrees/<name>), so its transcript lives under ~/.claude/projects/<repo>--worktrees-<name>/<session>.jsonl.
    2. The worktree was later removed. The thread record now has worktreePath: null and its provider session cwd is the repo root. Continuing the parent thread still works.
    3. Fork the thread (thread.fork from the latest assistant message) and send a message in the fork.

    Actual behavior: thread.fork is accepted, and the fork's first turn fails within ~2 s:

    ProviderAdapterForkThreadError: Failed to fork claudeAgent provider thread ...
      [cause]: ClaudeAgentSdkQueryRunnerError: Claude Agent SDK query failed.
        [cause]: Error: Session <session-id> not found in project directory for <repo root>
    

    The outgoing SDK frame is session.fork with sessionId: <session-id>, options.dir: <repo root>, options.upToMessageId: <latest assistant cursor>. The transcript sits under the worktree slug, so the dir-pinned lookup cannot see it. The provider-turn.start effect retries 3 times (~150–300 ms apart), then the run is marked failed; a second message in the fork fails identically.

    This looks like the same root cause described here (forkThread/forkOptions pinning dir to the thread's current cwd). Posting as a real-world confirmation that the transcript-under-a-previous-project-directory path also occurs when the source session was created in a worktree that T3 later removed, on 0.1.8. #22836 should cover it.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions