[BUG] VS Code: unarchiving a still-running archived session starts a second process on the same sessionId (both live, both messageable, transcript forks)
Summary
In the VS Code extension, unarchiving a session starts a second claude.exe process for the same sessionId while the archived session's original process is still running. The two processes then run concurrently:
- both are registered as live peers for cross-session messaging, under different auto-derived names and different named pipes;
- both append to the same transcript JSONL, which forks into two sibling branches. Neither process sees the other's branch.
The archived process was never stopped (the same root cause as #90712, reported there for the Desktop archive tool). But here it also stayed reachable by other sessions' SendMessage while archived, and kept acting on those messages. Unarchiving then produced a second live copy of the same conversation instead of reattaching to the running one.
Environment
- Claude Code 2.1.281, VS Code extension (
entrypoint: claude-vscode, native binary) - Windows 11 Home 10.0.26200
- Several interactive sessions open in different projects, using cross-session messaging (
ListAgents/SendMessage)
Steps to reproduce
- Open an interactive session in the VS Code extension (call it session S). Have a second session in another project that messages S.
- Archive S in the extension's session list, while S is mid-turn or idle.
- From the other session, run
ListAgents: S is still listed, and aSendMessageto it is delivered and acted on. - Unarchive S in the extension.
Expected
- Archiving stops S's process, or at least removes it from cross-session messaging (an archived session should not be a live peer).
- Unarchiving resumes the one session: a single process per
sessionId. The docs describe resume as a continuation, and only--fork-session//branchas a fork.
Actual
After unarchiving, %USERPROFILE%\.claude\sessions\ held two records with the same sessionId (and the same bridgeSessionId), for two live processes:
| | original (archived) | after unarchive |
|---|---|---|
| pid | A | B |
| name (nameSource: derived) | <project>-2d | <project>-77 |
| messagingSocketPath | \\.\pipe\LOCAL\cc-msg-773e… | \\.\pipe\LOCAL\cc-msg-3e54… |
| startedAt | 05:45:51 | 06:21:07 |
| process | still running | running |
Timeline from that morning:
- 06:21:07: process B starts (the unarchive).
- 06:21:08: process A, still mid-turn, runs a
git commitand pushes it, then writes a file in a sibling repository. - 06:22:01: process A goes
idle. It stays alive, and stays listed byListAgents, until killed by hand.
The transcript JSONL forked. At 06:21:00 one entry has two children. One is process A's continuation (its commit and file write); the other is process B's first entry, a synthesized assistant message "No response requested." that closed the turn it had loaded. B never loaded A's last entries, so B's model saw its own session's commit as having been made by "someone else."
Process A could not be stopped gracefully (taskkill → "can only be terminated forcefully"); taskkill /F was needed. After the forced kill its <pid>.json / .key stay in ~/.claude/sessions/ (ListAgents correctly ignores the dead PID).
Impact
Two live agents with the same conversation, both reachable by other sessions, act on the same messages independently. Here that caused a near-duplicate write into a coordination file shared with another repository, and it was avoided only because the second copy happened to check first. Commits made by one copy look foreign to the other.
Related
- #90712: archiving does not stop the session process (Desktop /
archive_session). This issue adds the VS Code archive path, archived sessions staying reachable over cross-session messaging, and the second process on unarchive.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗