[Bug]: Imported Claude Code threads fail on their first follow-up with "Session ID … is already in use"#15243

openedOct 3, 2026byAalimohammed1624

Before submitting

  • I searched existing issues and discussions. This was predicted from code reading in #15234 and juliusmarminge asked for a reproduction there.
  • This report includes the session details and the error text.

Area

apps/server

Steps to reproduce

  1. Run a Claude Code session in a project folder from the terminal (for example claude in ~/work/<project>), so ~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl exists.
  2. Import that session into T3 Code through the existing session import (agentSessions.import via the welcome wizard at /welcome, or the per-session picker from #15234).
  3. Open the imported thread and send any follow-up message.

Expected behavior

The follow-up resumes the existing Claude Code session (resume: <sessionId>) and the turn runs.

Actual behavior

The turn fails immediately. The thread shows "Provider error / Provider turn failed." and its status becomes Failed. The server logs orchestration-v2.claude-query-stream-failed for the thread's provider turn with the cause elided.

Running the same thing the adapter does, directly against the CLI, shows the underlying error:

1$ cd ~/work/being-and-becoming
2$ claude -p --session-id e7f9c804-28e6-45bb-a19d-de63cd7bc206 "Reply with just the word ok."
3Error: Session ID e7f9c804-28e6-45bb-a19d-de63cd7bc206 is already in use.

Cause, from reading the code: AgentSessionImporter writes the imported provider thread with a strong nativeThreadRef but nativeConversationHeadRef: null and no provider turns. In ClaudeAdapterV2 openQuery, shouldResume is true only when there is a conversation head, the process already opened the session, or providerTurnOrdinal > 1. An imported thread has none of those on its first follow-up, so makeClaudeQueryOptions passes sessionId: <imported id> instead of resume: <imported id>, and the CLI rejects the id it already owns. The adapter's own comment at that spot describes exactly this failure. The provider_resume_fallback in ProviderTurnStartService does not catch it, because the Claude resumeThread is a no-op that succeeds and the failure happens later at query open.

Codex imports are unaffected: the Codex adapter sends thread/resume { threadId } for the same ref and the turn runs.

Impact

Major degradation or frequent failure. Every imported Claude Code session (wizard import or per-session import) fails on its first follow-up, so Claude sessions cannot be continued in T3 Code.

Version or commit

main at ce90eec1f (2026-10-03), reproduced on a branch that adds only the per-session picker from #15234 on top of it. Claude Code CLI: 2.1.286 (Claude Code).

Environment

macOS (Darwin 27), web client in the dev server (vp run dev with an isolated --home-dir), Claude Code provider instance with its default home.

Logs or stack traces

1[21:46:47.701] WARN (#8689): orchestration-v2.claude-query-stream-failed
2 {
3 providerSessionId: 'provider-session:provider-instance:claudeAgent:thread:import%3AclaudeAgent%3Ae7f9c804-28e6-45bb-a19d-de63cd7bc206:12ccf8a1-8a39-48d4-8f4a-1dc6129d0275',
4 providerThreadId: 'provider-thread:provider:claudeAgent:native-thread:e7f9c804-28e6-45bb-a19d-de63cd7bc206',
5 providerTurnId: 'provider-turn:provider:claudeAgent:native-turn:turn%3Arun-attempt%3Arun%3Arun%253Athread%253Aimport%25253AclaudeAgent%25253Ae7f9c804-28e6-45bb-a19d-de63cd7bc206%253Aordinal%253A1%3Aattempt%3A1',
6 cause: { _id: 'Cause', failures: [ [Object] ] }
7 }

Turn item persisted for the run: {"type":"error","title":"Provider error","failure":{"class":"transport_error","message":"Provider turn failed.","code":null,"retryable":null}}.

Workaround

None inside T3 Code. Resuming from the terminal with claude --resume <sessionId> works.

Related

  • #15234 (per-session continue proposal, where this was predicted)
  • Discussion #6873

Filed by alimohammed1624. Drafted with Claude Fable 5.1 in Claude Code.

Note

Grok responding on behalf of Julius.

Triage

Thanks @alimohammed1624 for turning the prediction from #15234 into a real repro, with the CLI command and the logs.

Confirmed on main at ce90eec1f. This isn't limited to the unmerged per-session picker. The welcome-wizard import goes through the same AgentSessionImporter path, so every imported Claude Code thread fails the same way on its first follow-up.

Your reading matches the code:

  • Import writes a strong nativeThreadRef, nativeConversationHeadRef: null, and no provider turns. It also stores a Claude resumeCursor of { threadId, resume }, but ClaudeAdapterV2 never reads that cursor.
  • The first follow-up's providerTurnOrdinal is 1, since import creates no provider turns.
  • In openQuery, shouldResume is false for an imported thread, so makeClaudeQueryOptions sends sessionId instead of resume. The comment at that spot describes exactly the "Session ID … is already in use" failure.
  • ClaudeAdapterV2.resumeThread just stamps the existing row and succeeds, so ProviderTurnStartService never takes the provider_resume_fallback path. The failure comes later, when the query opens.

Codex isn't affected, because its resumeThread sends thread/resume for the same native ref.

Likely fix area

shouldResume in ClaudeAdapterV2.openQuery could also treat an imported thread as resumable, for example by honoring the stored resumeCursor. Alternatively, the importer could record a conversation head. A maintainer will decide on the fix direction.

The per-session picker idea in #15234 remains a separate feature discussion.

Synced from GitHub

Still reproduces on main at da7c4f2 (desktop 0.1.0 beta, Claude Code 2.1.302), via the welcome-wizard import.

Two additions:

There is an in-app workaround: resend the message. The second attempt in the same thread succeeds. After the failed open, the native id is in openedNativeThreads, so shouldResume becomes true and the retry sends resume (ClaudeAdapterV2.ts around L8122). Provider log from my run:

115:29:03 query.open { model: claude-fable-5-1, sessionId: 280712f5-... } -> "Session ID ... is already in use"
215:29:36 query.open { model: claude-opus-5-5, resume: 280712f5-... } -> ok

The model switch between the two attempts is incidental; any resend works.

Both attempts also carried a manual_context handoff of the imported transcript, even though the resumed native session already contains that history. Once the resume fix lands, that handoff is redundant context for imported Claude threads.

Reproduced on Linux with Claude Code 2.1.303 and current main b5a226e49c, using vp run dev with isolated worktree state. Created a terminal Claude session, imported it through /welcome, then sent its first follow-up. The app showed “Provider turn failed”; the provider log recorded query.open with sessionId instead of resume. The same CLI invocation returned “Session ID … is already in use.” Resending in the imported thread succeeded with resume and returned the requested response.

Fix proposed in #23202. On Linux with Claude Code 2.1.303, the imported session now succeeds on its first follow-up, on a subsequent turn, and after a server restart. Runtime evidence. Focused server tests: 230 passed.

Synced from GitHub

Still reproduces on T3 Code desktop nightly 0.1.6-nightly.20261030.3917, macOS 26.7.1, Claude Code 2.1.314.

The first follow-up in an imported Claude conversation fails with “Provider error.” The provider log records query.open with sessionId rather than resume, followed by prompt.offer and no incoming events. The persisted failure is transport_error / “Provider turn failed.”

Verified with SDK initialization requests only, without sending an inference prompt:

  • --session-id <existing-id> exits 1: “Session ID is already in use.”
  • --resume <same-id> exits 0 with a successful initialization response.

A fresh T3 Claude conversation worked on the same installation. No app or database changes were made. The resend workaround mentioned above was not tested.

Investigated and drafted by Codex (GPT-6), on behalf of the affected user.

Synced from GitHub

Same failure here on T3 Code 0.1.5 (beta), macOS 26.7.2, Claude Code 2.1.314: imported thread, first follow-up, query.open sent sessionId and the turn failed with "Provider turn failed".

Synced from GitHub

Still reproduces on t3 0.1.6 (stable, Linux server, macOS Beta client) with Claude Code 2.1.316. First follow-up on an imported thread fails in ~200 ms; the provider log shows query.open with sessionId: <imported id> (not resume), and claude -p --session-id <existing id> reproduces "Session ID … is already in use". #15376 / #23219 would fix it.

Synced from GitHub

One case that resending doesn't get past, and that #15376 / #23219 won't fix: the imported conversation is still owned by a Claude Code background session (claude --bg; its ~/.claude/sessions/<pid>.json has "kind":"bg" and a live pid).

On T3 Code (Beta) desktop 0.1.6, local server, macOS 27.0.1, Claude Code 2.1.316: the first follow-up failed as described here, and then every resend failed after about 1 s. By then the adapter was sending resume: <id>, but the CLI refuses to resume a session that a background job owns:

1Error: That session is running in the background (<short id>). Run `claude attach <short id>` to open it, or `claude stop <short id>` first to resume it here. Add --fork-session to branch off a copy instead.

T3 discards that stderr, so the thread shows only "Provider turn failed." (the same reporting gap as #26082 / #26382). The only server-side trace for each attempt is orchestration-v2.claude-mcp-servers-unavailable (servers: t3-code), because the CLI exits before MCP registration (ClaudeAdapterV2.ts:1083 at v0.1.6). Nothing in ClaudeAdapterV2.ts at v0.1.6 or at main 0847a448fd handles this case.

I reproduced it outside T3 using @anthropic-ai/claude-agent-sdk 0.3.276 (the version T3 pins) with T3's query options (resume, bypassPermissions, includePartialMessages, effort medium, adaptive thinking with summaries, settingSources user/project/local), on a throwaway session:

Who owns the sessionResult
Nothing elseinit 541 ms, result ok
Another SDK query() holding it openinit 666 ms, result ok
An idle claude --bg jobexit 1 at 753 ms, the error above
Same session after claude stop <short id>init 534 ms, result ok

Workaround: claude stop <short id> (or claude attach <short id> and exit), then resend in T3. stop needs the 8-character job id that the error prints. Passing the full session UUID returns "No job matching".

Possible fixes (for maintainers to choose from): show the CLI's stderr as the turn error, check for a live kind: "bg" owner before resuming, or offer to continue from a fork (the CLI itself suggests --fork-session).

Filed by Claude Code (Claude Opus 5.5), following .github/triage/PLAYBOOK.md.