Repository navigation
Claude thread loses context and cannot fork after its provider association moves to an imported thread #17236
Description
Activity
Note
Grok responding on behalf of Julius.
Thanks for the detailed write-up. The synthetic DB state you describe lines up with what main does today (checked at
a6ec88f7a). The likely cause is that the bulk importer builds the same provider-thread id the live Claude adapter already used for that session, and the projection upsert then moves the record over to the imported thread.How
Plikely changed owner- The bulk importer (thread id
import:<instance>:<session>,apps/server/src/project/AgentSessionImporter.ts:226-228) only checks for an existing thread under thatimport:id (:252-266). It never checks whether a native thread already owns the session. That's the gap tracked in Imported agent sessions duplicate T3-native threads: import dedup never consults the native thread namespace #10933. - It derives the provider-thread id from the driver and native session id without the provider instance (
AgentSessionImporter.ts:270-273). The native Claude adapter derives it the same way (Adapters/ClaudeAdapterV2.ts:1113-1116), so both produce the sameP(IdAllocator.ts:216-232). By contrast, the per-session import path includesproviderInstanceId(Orchestrator.ts:2241-2245), so it shouldn't collide. - The import then writes
provider-thread.updatedwithappThreadIdset to the imported thread (AgentSessionImporter.ts:312-318,:352-375). The projection upsert isON CONFLICT(provider_thread_id) DO UPDATE SET thread_id = excluded.thread_id, …(orchestration-v2/ProjectionStore.ts:2193-2206), soP'sthread_id/payload_jsonsilently switch toimport:claudeAgent:…. That matches what you saw. - On main, the only client that calls
agentSessions.importseems to be the welcome wizard's import step (apps/web/src/components/onboarding/WelcomeWizard.tsx:1215), and visiting/welcomereopens it (apps/web/src/routes/welcome.tsx:13). So my best guess is that onboarding or import was re-run for a project that already had native Claude threads. I haven't confirmed that.
How that explains the three symptoms
- Context loss (run 20): a thread's provider threads are loaded by
thread_id(ProjectionStore.ts:3020-3038). ThreadAstill hasactiveProviderThreadId = P, butPno longer appears in its projection, soactiveProviderThreadis undefined (Orchestrator.ts:4842-4844). The next send then mints a newpending:<runId>provider thread (Orchestrator.ts:5221-5226), which means a new native Claude conversation with no handoff. - Fork failure:
providerThreadForRunsearches only that same per-thread list (Orchestrator.ts:640-647). For run 19 it returns undefined, which trips the guard atOrchestrator.ts:5569-5574. - UNIQUE error on the imported thread: the next provider-turn ordinal is computed only from the current thread's
providerTurns(ProviderTurnStartService.ts:1248-1254). The imported thread has none underP, so it picks ordinal 1, butA's turns already hold(P, 1…). That conflicts with the unique index on(provider_thread_id, ordinal)(persistence/Migrations/055_OrchestrationV2.ts:178).
Origin: the v2 importer that emits this deterministic id arrived with the new orchestrator in #2829. The v1 importer from #5362 created duplicates (#10933) but didn't share provider-thread records.
Related work
- fix(server): skip native sessions during bulk import #15634 (open) looks like it would prevent new cases. It skips the import when another thread already owns the same driver, instance and native id, and it also adds
providerInstanceIdto the importer's derived id. Its own description says it doesn't repair existing rows, so affected databases would still need a repair step. - fix(server): imported Claude Code sessions resume on their first follow-up #15376 (open) is a different import bug: imported Claude sessions fail on the first follow-up ([Bug]: Imported Claude Code threads fail on their first follow-up with "Session ID … is already in use" #15243). As far as I can tell it wouldn't prevent this collision.
- [Bug]: Session context get's lost/forgotten if i leave it for a while #2256 has a similar symptom but predates v2. I didn't find a duplicate.
Possible fix directions (untested)
- Land a native-ownership guard like the one in fix(server): skip native sessions during bulk import #15634, plus an instance-scoped importer id.
- As a safety net, have the projection upsert refuse to change
thread_idon an existing provider thread that other threads' runs still reference. - Add a one-off repair that gives
Pback to the thread whose runs reference it, and detaches or retires the colliding imported thread.
Workaround (not verified): don't continue or fork the imported thread, since that keeps hitting the unique constraint. I haven't found an in-app action that hands
Pback toA. A projection rebuild would most likely replay the import event afterA's events and land in the same state. For now, your approach (export the transcript and have a fresh thread read it) seems to be the safest way to recover.- The bulk importer (thread id
- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.
on Oct 8, 2026
What happened
An existing Claude conversation continued displaying its history in T3, but the agent could no longer see the earlier messages. Forking from a response before the context loss also failed.
Investigation found a separate imported thread associated with the original Claude session. Attempting to continue that imported thread failed with a database uniqueness error.
The conversation text and native Claude session file were still present. Recovery required exporting the saved messages and having a fresh thread read them.
Diagnosis
The persisted state suggests a collision between an existing thread and an imported representation of the same native Claude session.
Using synthetic identifiers:
Ahas runs 2–19 referencing provider threadP.Phas boththread_idandpayload_json.appThreadIdpointing toimport:claudeAgent:SESSION_X, rather thanA.P.Astarts a different native Claude conversation. Runs 20–22 have no recordedcontextHandoffId.The fork error matches the guard in
Orchestrator.tsthat rejects a pending fork when its source run or source provider thread cannot be resolved.Suspected cause: importing the native session reassigned a provider-thread record already referenced by the original application thread. The resulting database state is confirmed; the exact action or background process that produced it has not been established. Source inspection used
main, not an exact build checkout.Steps to reproduce
A deterministic reproduction has not yet been established. The observed sequence was:
It is unknown whether importing was explicitly initiated or performed automatically.
Version
Affected desktop app: 0.0.46-nightly.20261008.2819. The separately invoked triage CLI reported 0.0.45. The affected desktop logs and database used the nightly version and statev2.sqlite.
Environment
macOS, Darwin 25.5.0, arm64; T3 Code Nightly desktop app with local server; provider claudeAgent; model claude-opus-5-5; triage Node.js v26.8.2.
Evidence
Related issues
#2256 describes a similar visible-history/context-loss symptom, but does not establish this provider-association collision or the accompanying fork and uniqueness failures. No confirmed duplicate was identified.
Fix applied or workaround
Backed up the native Claude session and exported the original thread’s 80 saved messages. A fresh Claude thread read the complete transcript and successfully summarized the previous decisions and outstanding work.
This recovered written context without directly editing the database. It did not repair the original thread association or restore internal reasoning/tool state.
Filed by
Prepared by GPT-6 Astra in Codex via
t3 triage.