[BUG] Crashed session can be resumed into multiple concurrent live processes sharing one transcript (session forking + ghost roster entries)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [ ] I am using the latest version of Claude Code
What's Wrong?
Environment
- PC: Ryzen 2200G, 8GB RAM.
- Claude Code version: 2.1.227
- OS: Ubuntu 22.04, kernel 7.0.0-29-generic
- Session profile: very long-running session (multiple /compact cycles), heavy background usage (background Bash tasks, background subagents via the Agent tool), sandboxed filesystem enabled , with limited RAM and CPU resources
What happened
Over ~16 hours our main session froze/crashed several times. After each freeze we resumed it (/resume, sometimes from a new terminal while the frozen process had not been cleaned up). Result: the same transcript ended up with multiple concurrent live processes, each continuing independently from the shared history, each believing it was the only one. At peak, the session picker / agent roster showed seven entries with the identical auto-generated name (several of them ghosts — dead processes whose registrations were never cleaned up).
The forked continuations went on to do real, divergent work in parallel on the same git repository for many hours (same memory dir, same task list, same working conventions — they are indistinguishable by name, memory, or style; only git log authorship of specific commits could tell them apart).
Expected behavior
shown below
Actual behavior
- Multiple live processes ran concurrently from one transcript; process IDs changed on every crash/restart while the displayed session name (derived from transcript content) stayed identical, making entries indistinguishable.
- Ghost registrations persisted after crashes; cross-session messaging by name became a lottery (one continuation saw an empty agent list; another saw seven identically-named entries via the Remote Control channel and had to broadcast "if commit X is yours, you are the real one" to disambiguate).
- Background tasks running at crash time were orphaned with no completion record (expected on crash, but combined with forking, several continuations each re-drove the "same" pending pipeline).
Impact
- High risk of concurrent writers on the same git branch: we observed two near-miss double-write incidents (both caught by our own repo-side discipline, not by the tool).
- Uncommitted state was lost or left inconsistent across forks (a worktree vanished with the per-session tmpfs; a review conclusion sat uncommitted in one fork while another fork could not see why the worktree looked dirty).
- A SIGKILL mid-run also left a test's in-place mutation un-restored (our own test's trap didn't fire) — separate issue on our side, but the crash frequency amplified it.
What Should Happen?
- Resuming a session that already has a live process should either attach/replace it or refuse with a clear warning — not silently start a second live continuation of the same transcript.
- A crashed process's roster/registration entry should be invalidated so the picker doesn't accumulate identical ghost entries.
- Ideally, transcripts would carry a liveness lock (with staleness detection) so crash + resume converges to exactly one live continuation.
Error Messages/Logs
## Error messages / logs
No crash stacktrace is available — the process freezes silently (no output) and was killed/exited without writing an error. The observable evidence is behavioral:
1. After each restart, orphaned-task notifications like:
No completion record was found for background agent "..." from the previous session.
It may have been stopped, or it may have been running when the previous Claude Code process exited.
No completion record was found for this background shell command from the previous session.
2. Cross-session addressing failures while duplicates existed:
SendMessage: No agent named 'X-structure builder1' is reachable.
Use ListAgents to see everyone you can message.
(one live continuation's `ListAgents` returned "No reachable agents" while another continuation could see **seven identically-named entries** for the same lineage via the Remote Control channel)
3. A session renamed by the user in the picker did not propagate — it still appeared under the old auto-generated name in the other continuation's roster.
Steps to Reproduce
Reproduction (best effort)
- Run the ClaudeCode in a PC with limit CPU and RAM resource
- Run a long session with several background tasks in flight and let the process freeze/be killed (we hit this repeatedly; the freezes correlated with heavy background activity around compaction).
- Without cleaning up the frozen process, open a new terminal and
/resumethe same session; repeat across a few crash cycles. - Observe: multiple live processes for one transcript; picker/roster accumulates identically-named entries; each continuation proceeds independently.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.227
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Other
Additional Information
Notes
- All forks shared the persistent memory directory and project task list, so they cooperated accidentally well — the danger is precisely that they are indistinguishable and unaware of each other.
- Happy to provide sanitized timelines (git reflog + our append-only event ledger) if useful.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗