You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ACP: session/load in the same UTC minute as session/new fails with "No previous sessions found" — and durably destroys the session's resumability #28693
Updated 2026-08-09 — root cause identified; original framing corrected. The original report claimed a crashed session is "never persisted". That's wrong: persistence is fine (every record is written synchronously, and the conversation file survives any kill). The real defect is in the load path: session/load eagerly re-initializes chat recording for the requested session id before resolving it, appending a fresh metadata header + $set {messages: [<session_context>]} checkpoint to session-<UTC-minute>-<id[0:8]>.jsonl. When the load runs in the same UTC minute the session was created, that append lands in the session's own conversation file; the checkpoint buries the conversation in the fold, hasResumableContent flips false, the session is filtered from the listing, and the load fails with No previous sessions found for this project — after durably destroying the session's resumability. No crash is required (it reproduces after a clean exit). Full mechanism with source refs at cf22ac7, a three-variant repro on 0.54.0, and the likely unification with #27913: see this comment.
What happened
When gemini runs as an ACP agent, initialize advertises agentCapabilities.loadSession: true — but a session/load issued in the same UTC minute as the session's session/new fails with:
No previous sessions found for this project
and durably poisons the session file, so every later session/load for that id fails too. Automated ACP clients (an editor reconnecting right after a crash, scripted harnesses) land in this window routinely; a human retrying minutes later lands in a different minute and sees loads succeed, which makes the failure look intermittent or environment-dependent.
Version
Originally observed on gemini 0.53.0; root-caused and reproduced on 0.54.0, macOS/arm64, driven over stdio by a minimal ACP client. Mechanism present in source at cf22ac7.
Steps to reproduce (no crash or kill required)
Start gemini in ACP mode; initialize → loadSession: true.
Run one or more session/prompt turns to completion.
End the process — cleanly (close stdin, exit 0) or by SIGKILL of the process tree; both reproduce.
Spawn a fresh gemini ACP process; initialize; session/load ({ sessionId, cwd, mcpServers: [] }) — within the same UTC minute as step 2.
Expected
session/load finds the session (its file is on disk with all turns) and replays the conversation per the ACP spec — and, being a read operation, does not modify the session it is resolving.
Actual
Step 5 fails with No previous sessions found for this project, and the session's session-<minute>-<id8>.jsonl gains a trailing metadata header + $set {messages: [<session_context>]} checkpoint written by the load call itself, permanently burying the conversation in the fold (the turn records remain physically present in the file, before the poison pair). Later session/load calls — in any minute — keep failing, each leaving an additional context-only junk file.
Historical note on the original report
The original report reproduced this via SIGKILL of the whole process tree mid-turn and framed it as missing crash persistence. The tree-kill observation itself stands — each launch self-re-execs a sandbox wrapper, so killing only the spawned pid orphans the real agent, and probes must kill the tree — but neither the kill nor its timing is load-bearing for this bug: the probe's new → turns → kill → load sequence simply always landed inside one minute.
Related
#27913 is very likely the same root cause observed one release earlier: it was filed against 0.46.0, before 3a13b8eeb (#27770, first shipped in v0.47.0) added the hasResumableContent filter. Pre-filter, the poisoned fold still lists, so session/load "succeeds" — replaying exactly one user_message_chunk (the <session_context>, which streamHistory doesn't filter) while the model's restored history is empty (convertSessionToClientHistory filters it out). Post-filter, the identical on-disk state reports No previous sessions found instead.
Note
Updated 2026-08-09 — root cause identified; original framing corrected. The original report claimed a crashed session is "never persisted". That's wrong: persistence is fine (every record is written synchronously, and the conversation file survives any kill). The real defect is in the load path:
session/loadeagerly re-initializes chat recording for the requested session id before resolving it, appending a fresh metadata header +$set {messages: [<session_context>]}checkpoint tosession-<UTC-minute>-<id[0:8]>.jsonl. When the load runs in the same UTC minute the session was created, that append lands in the session's own conversation file; the checkpoint buries the conversation in the fold,hasResumableContentflips false, the session is filtered from the listing, and the load fails withNo previous sessions found for this project— after durably destroying the session's resumability. No crash is required (it reproduces after a clean exit). Full mechanism with source refs atcf22ac7, a three-variant repro on 0.54.0, and the likely unification with #27913: see this comment.What happened
When
geminiruns as an ACP agent,initializeadvertisesagentCapabilities.loadSession: true— but asession/loadissued in the same UTC minute as the session'ssession/newfails with:and durably poisons the session file, so every later
session/loadfor that id fails too. Automated ACP clients (an editor reconnecting right after a crash, scripted harnesses) land in this window routinely; a human retrying minutes later lands in a different minute and sees loads succeed, which makes the failure look intermittent or environment-dependent.Version
gemini0.53.0; root-caused and reproduced on 0.54.0, macOS/arm64, driven over stdio by a minimal ACP client. Mechanism present in source atcf22ac7.Steps to reproduce (no crash or kill required)
initialize→loadSession: true.session/new({ cwd, mcpServers: [] }) →sessionId.session/promptturns to completion.initialize;session/load({ sessionId, cwd, mcpServers: [] }) — within the same UTC minute as step 2.Expected
session/loadfinds the session (its file is on disk with all turns) and replays the conversation per the ACP spec — and, being a read operation, does not modify the session it is resolving.Actual
Step 5 fails with
No previous sessions found for this project, and the session'ssession-<minute>-<id8>.jsonlgains a trailing metadata header +$set {messages: [<session_context>]}checkpoint written by the load call itself, permanently burying the conversation in the fold (the turn records remain physically present in the file, before the poison pair). Latersession/loadcalls — in any minute — keep failing, each leaving an additional context-only junk file.Historical note on the original report
The original report reproduced this via SIGKILL of the whole process tree mid-turn and framed it as missing crash persistence. The tree-kill observation itself stands — each launch self-re-execs a sandbox wrapper, so killing only the spawned pid orphans the real agent, and probes must kill the tree — but neither the kill nor its timing is load-bearing for this bug: the probe's new → turns → kill → load sequence simply always landed inside one minute.
Related
#27913 is very likely the same root cause observed one release earlier: it was filed against 0.46.0, before
3a13b8eeb(#27770, first shipped in v0.47.0) added thehasResumableContentfilter. Pre-filter, the poisoned fold still lists, sosession/load"succeeds" — replaying exactly oneuser_message_chunk(the<session_context>, whichstreamHistorydoesn't filter) while the model's restored history is empty (convertSessionToClientHistoryfilters it out). Post-filter, the identical on-disk state reportsNo previous sessions foundinstead.