[Bug] Main agent state lost when resuming session from Claude Agent Panel
Status Open
Reported on v2.1.198
Maintainer reply None cached
Activity 5 comments · opened Jul 2, 2026
Bug Description
this session had a serious bug, the main agent is lost when I get back to this session from claude agent panel.
Environment Info
- Platform: darwin
- Terminal: xterm-256color
- Version: 2.1.198
- Feedback ID: 35189f78-ab9c-4bb1-b25d-ccd13a496d97
Errors
[]
5 Comments
Yeah I experience the same - when you accidentally get into the agents view by pressing left and then try to go back into the session, it just re-sends the last prompts and forgets anything it did in between (e.g. active subagents)
我已收到您的邮件!会尽快予以回复!
Having the same issue, it's frustrating @bcherny could you take a look?
Adding root-cause detail after hitting this 5+ times in the last two days (v2.1.201 and also v2.1.198, macOS). I dug into the on-disk transcripts under
~/.claude/projects/<project-dir>/and the mechanism is visible there.TL;DR: every subagent/teammate transcript is written as a sibling top-level session file with no parent pointer, and it inherits the parent session's
ai-title— so--continue, the--resumepicker, and the agent panel can surface a subagent transcript that looks identical to the main session. Once resumed, that file is the whole session; the main agent lives in a different file that nothing references, so there is no way back from inside.On-disk evidence (a main session + Explore/teammate subagents it spawned):
{"type":"agent-setting","agentSetting":...,"sessionId":"<own id>"}. The subagent files carry noparentSessionId(the headparentUuidisnull— that field chains messages, not sessions), and their message entries haveisSidechain: false.agentSettingis not a discriminator: teammates spawned as general-purpose agents record"agentSetting": "claude", same as a real main session (only some record"Explore"etc.).ai-titlerecords duplicate the parent session's title:{"type":"ai-title","aiTitle":"<parent session title>"}aiTitle, with only theagent-namerecords differing (explore-front,explore-backend, …)That's exactly why the picker shows several identically-titled entries — and the most recently touched one is usually a subagent.
usermessage is the spawn prompt (e.g. starts with<teammate-message teammate_id="team-lead">) instead of a human prompt.Why the top entry is a subagent: when a session is interrupted or hangs, subagent files finalize after the main file stops being written; and merely opening a transcript from the picker touches its mtime, so a single wrong pick makes that subagent the durable "most recent" entry and
--continuekeeps landing on it. (Compounding: verifying a candidate with--resume <id> --fork-session -p ...creates yet another sibling file that becomes the new top entry.)Impact: in every one of my cases the main transcript was intact — all
Agenttool_use/tool_result pairs completed, deliverables present. The work isn't lost, it's just unreachable through the UI. Recovery that works every time:Suggested fixes:
parentSessionId(+ spawnagentName) into subagent transcript headers, and have--continue/ the--resumepicker / the agent panel exclude them or group them under their parent.<teammate-message …>/ agent spawn block).Happy to share sanitized transcript headers if useful. Related: #70170 (same dead-end for sessions held as background agents).
Confirming this bug on Windows (Claude Code v2.1.202, Windows 11), with an additional evidence variant not covered above: metadata-only ghost session files that get re-created after deletion because
~/.claude.jsonstill points at them.Additional symptoms observed
Every time I run
/rename,/color, or/modefrom a background-job session, the events land in a different session file than my chat transcript. The result is a "ghost" JSONL file that contains ONLY:custom-title, agent-name, agent-color, mode, permission-mode, hook_success, attachment
Zero user messages, zero assistant messages, zero tool calls. This is a different failure mode than r-po's subagent-inheritance case — my ghost files have no conversation content at all.
Root cause (Windows-side observation)
~/.claude.jsonstoreslastSessionIdper project. Frontend UI commands (rename, color, mode) write tolastSessionIdregardless of which session ID owns the current transcript. So:/rename foo→ session B (whateverlastSessionIdpoints at, which can be a stale bg-worker sidecar)Even after archiving session B's
.jsonl, Claude Code silently re-creates it on the next UI command becauselastSessionIdstill references it. The re-created file is 13KB of metadata-only events.Repro (Windows)
/rename fooand/color orange.~/.claude/projects/<hash>/:<active-id>.jsonl— has user/assistant/tool_use events<lastSessionId>.jsonl— contains ONLY the rename/color/mode events/resumepicker shows two entries titled "foo", one with a real conversation, one empty..jsonl. Run/rename fooagain → ghost is re-created.Evidence from my project dir
~/.claude/projects/C--Users-...-Konnect/
├── 16999f09-...jsonl 813 KB full transcript
└── 4178b92d-...jsonl 13 KB metadata-only ghost
.claude.jsonline ~2087:"lastSessionId": "4178b92d-..."— the pointer that keeps re-summoning the ghost.Compounding effect with r-po's subagent-inheritance bug
I've spawned three background subagents in this session over the past hour. Each one inherits the session title "MCP to Konnect Migration" (per r-po's finding). Combined with the
lastSessionIdmetadata-ghost mechanism, my/resumepicker now shows FIVE entries titled "MCP to Konnect Migration", each landing at a different point in the conversation. The main transcript is intact and reachable via the grep recovery workflow, but the picker experience is unusable.Suggested fixes (adds to r-po's list)
/rename,/color,/mode) must write to the active session ID, notlastSessionId. UpdatelastSessionIdat the same time so it stays in sync..jsonlfor a session ID that was deleted from disk — treat disk-absent as authoritative "session gone"./resumepicker should filter out session files that contain zero user or assistant messages (metadata-only ghosts).