[Bug]: Claude thread resumes the pre-/clear session, so replies go to the old conversation#24153

opened5d agobySstromseng

Note

Written by Claude (Claude Code, Opus 5.5) on behalf of @stromseng, from the session transcripts on their machine.

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. Work in a Claude thread until it holds a long session (here ~700K tokens, session A).
  2. Send /clear. Claude Code starts a new session B, and the thread keeps working in it.
  3. Run a few turns in B (here a /grill-with-docs skill that asked numbered questions Q1–Q13).
  4. Some minutes later, reply in the same thread to B's last message ("9. yes, 10. yes, …").

Expected behavior

The reply goes to session B, the one the thread has shown since the /clear.

Actual behavior

The reply resumes session A, the one from before the clear. In the Claude transcripts the reply is written to A's JSONL, with parentUuid set to A's last assistant message from before the /clear. B's questions never show up in A. The agent answers that it has no numbered questions open, even though they're on screen right above. Because A is near the context limit, the turn autocompacts too.

From the user's side, the thread silently swaps the model's memory back to the old conversation. The UI gives no sign of it.

Impact

Major degradation or frequent failure

Version or commit

0.1.1-nightly.20261018.3315 (desktop)

Environment

macOS 26 (Darwin 25.6.0), T3 Code Nightly desktop, Claude Code 2.1.309, Claude Opus 5.5 (1M context)

Logs or stack traces

shell
1# session A (pre-clear), ~56 MB
225ad7bf9-….jsonl last turn before /clear: 13:25:45Z
3# session B (post-clear), ~0.5 MB
480ecc5d8-….jsonl /clear 13:36:03Z, /grill-with-docs 13:36:13Z, last assistant message (Q9–Q13) 13:45:18Z
5# reply "9. yes … 13. yes", 13:51:33Z, appended to A (parentUuid = A's 13:25:45Z message), not to B

Workaround

Start a new T3 thread instead of using /clear.

Notes

This is the Claude half of #19356 and #20078. Both were closed as duplicates of #7402. #7402 was then closed as a Codex /clear enhancement, and its last comment says "The Claude session-id restoration described above is a separate provider behavior". That leaves no open issue for it. #19356 traced it to the Claude adapter keeping the nativeThreadRef.nativeId stored at thread creation, rather than the session_id Claude Code reports after /clear. Here too it was triggered by a server restart between the two turns (see Root cause).

Root cause

Traced on main @ 66ee628e0 (apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts), and confirmed in this thread's provider log:

Time (UTC)Provider event
13:36:03/clear → Claude Code emits conversation_reset, then system/init with the new session_id (B)
13:36–13:45Turns run in B
13:45:34T3 server restarts (SessionStore.markDisconnected, getRecoveryThreadIds) → query.close
13:51:33Next prompt → query.open with "resume": "<A>", the session from before /clear
  1. The thread's Claude session id is providerThread.nativeThreadRef.nativeId. It is set once, when the provider thread is created (nativeThreadRef: { nativeId: input.nativeThreadId, … }, around line 1670), and never updated afterwards.
  2. After /clear, Claude Code reports the new id in system/init (message.session_id). The init handler (around line 9390) only reads permissionMode from it. conversation_reset isn't handled anywhere.
  3. Whenever the process has to be reopened, makeClaudeQueryOptions passes resume: input.nativeThreadId (around line 1339), which is still the pre-clear id. That happens after a server restart, after the 30-minute idle release, or after a model or permission change that can't be applied live.

So /clear only holds while the same Claude process stays alive. The first time the process is reopened, the thread goes back to the old conversation.

Possible fix: when system/init (or conversation_reset) carries a session_id that differs from nativeThreadRef.nativeId, persist the new id on the provider thread. That could go through the same provider-thread update the turn-end path already emits (around line 6880), so every later resume targets the current session.

Synced from GitHub

Note

Written by gpt 6.1 sol on behalf of Luke

Opened #24168 for this. It persists the native session ID Claude reports after /clear and keeps the live process’s task/wake routing attached to it, so a later process replacement resumes the cleared conversation.

The baseline regression fails because the saved ID stays on the old session. The final Claude adapter suite passes all 210 tests, including active/idle clears, ignoring subagent init IDs, live query reuse, and resuming the new ID after replacing the process. Server typecheck and scoped checks pass. Independent review caught lifecycle races that are addressed in the PR.

The description links sanitized evidence and states the gaps: this uses SDK replay, not a live authenticated /clear or packaged desktop run. Maintainer triage and lifecycle review are still requested.

Reproduced with the real web dev client and authenticated Claude on main fef851bee0: after /clear, a new-session question, and a server restart, the reply returned to the old transcript. Updated the existing #24168. The final runtime proof stays in the cleared session and remembers the question; the old transcript remains unchanged. All 418 focused tests pass after merging main. Packaged macOS desktop was not run.

Synced from GitHub

Still reproducing on the nightly, with a trigger that doesn't need a server restart.

  • Version: 0.1.4-nightly.20261027.3770, macOS desktop app, local server. I also checked the source at tag v0.1.4-nightly.20261028.3824: it doesn't include #24168 yet, so today's nightly is still affected.
  • Trigger without a restart: after /clear at 09:52 (Europe/Paris), the thread worked in the new session for almost three hours. At 12:39:55 T3 closed the Claude query, about a minute after a backgrounded dev-server task in that thread exited (likely related, not proven). The next turn, at 12:40, resumed the pre-/clear session and the agent picked up the old conversation's task.
  • Frequency on this machine: 3 affected threads out of 135 thread logs since Oct 17. In one of them, the old session was resumed on 8 turns between Oct 24 15:53 and Oct 25 09:37, so everything after the /clear was invisible to the model each time.

Workaround in use until #24168 ships: no /clear in T3, a new thread instead.

Diagnosed with Claude Code (Claude Opus) following the t3 triage playbook, posted on behalf of Martin.