Skip to content

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

Closed

Description

@alimohammed1624

Before submitting

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 [Feature]: Continue a Codex or Claude Code session started in the terminal as a T3 Code thread #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:

$ cd ~/work/being-and-becoming
$ claude -p --session-id e7f9c804-28e6-45bb-a19d-de63cd7bc206 "Reply with just the word ok."
Error: 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 ce90eec (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

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

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

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

Activity

  1. juliusmarminge commented on Oct 3, 2026

    @juliusmarminge
    Member

    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 ce90eec. 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.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 3, 2026
  3. benthecarman commented on Oct 8, 2026

    @benthecarman
    Contributor

    I have this same issue!

  4. felho commented on Oct 17, 2026

    @felho

    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:

    15:29:03  query.open  { model: claude-fable-5-1, sessionId: 280712f5-... }  -> "Session ID ... is already in use"
    15: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.

  5. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    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.

  6. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    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.

  7. ramhoj commented on Oct 30, 2026

    @ramhoj

    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.

  8. thnk2wn commented on Oct 30, 2026

    @thnk2wn

    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".

  9. mtthwsar commented on Nov 2, 2026

    @mtthwsar

    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.

  10. MatthewRamsey commented on Nov 2, 2026

    @MatthewRamsey

    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:

    Error: 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 session Result
    Nothing else init 541 ms, result ok
    Another SDK query() holding it open init 666 ms, result ok
    An idle claude --bg job exit 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.

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

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions