fix(gemini): graceful fallback for stale Gemini session IDs on resume#812
fix(gemini): graceful fallback for stale Gemini session IDs on resume#812bourgois wants to merge 4 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughDetect/stash "invalid session identifier" stderr, refresh stored cliSessionId from ChangesStale Resume Session Handling
sequenceDiagram
participant Client
participant spawnGemini
participant sessionManager
participant GeminiCLI
Client->>spawnGemini: start request (may include sessionId)
spawnGemini->>sessionManager: read stored cliSessionId / resumeId
spawnGemini->>GeminiCLI: spawn with --resume <cliSessionId> or --resume latest
GeminiCLI-->>spawnGemini: stderr "invalid session identifier"
spawnGemini->>spawnGemini: set stderrHasInvalidSession and buffer stderr
alt exit code 42 and stderrHasInvalidSession and not _retried
spawnGemini->>sessionManager: clear stored cliSessionId
spawnGemini->>spawnGemini: retry with _retried:true and _resumeLatest:true
spawnGemini->>GeminiCLI: spawn with --resume latest
GeminiCLI-->>spawnGemini: successful resume
spawnGemini-->>Client: complete
else no retry
spawnGemini-->>Client: flush buffered stderr and complete
end
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
server/gemini-cli.js (1)
473-478: 💤 Low valueConsider suppressing the error message when retry is planned.
The "invalid session identifier" error is sent to the client (line 478) before the retry occurs. This could confuse users who see an error followed by a successful stream. If the intent is a seamless retry, consider gating the
ws.sendon line 478 similarly to how the 'complete' event is suppressed.♻️ Optional: suppress error message before retry
if (errorMsg.toLowerCase().includes('invalid session identifier')) { stderrHasInvalidSession = true; + // Don't surface this error to the client; we'll retry with --resume latest + return; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/gemini-cli.js` around lines 473 - 478, The code sends an error message for "invalid session identifier" immediately via ws.send(createNormalizedMessage(...)) even when a retry is planned; update the logic around the error handling so that when stderrHasInvalidSession is set (i.e., when errorMsg.toLowerCase().includes('invalid session identifier')), you suppress or skip the ws.send call for that specific error path (use the same gating logic used for the 'complete' suppression) and only send an error to the client if no retry will occur; check getSessionId()/capturedSessionId/sessionId to build the socketSessionId as before but early-return or skip ws.send when a retry is intended.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@server/gemini-cli.js`:
- Around line 473-478: The code sends an error message for "invalid session
identifier" immediately via ws.send(createNormalizedMessage(...)) even when a
retry is planned; update the logic around the error handling so that when
stderrHasInvalidSession is set (i.e., when
errorMsg.toLowerCase().includes('invalid session identifier')), you suppress or
skip the ws.send call for that specific error path (use the same gating logic
used for the 'complete' suppression) and only send an error to the client if no
retry will occur; check getSessionId()/capturedSessionId/sessionId to build the
socketSessionId as before but early-return or skip ws.send when a retry is
intended.
Gemini CLI assigns a new internal session ID on each run, causing the stored cliSessionId to go stale. Subsequent --resume <id> calls fail with exit code 42 and "Invalid session identifier" in stderr. Three changes: - onInit now always refreshes cliSessionId instead of only writing it once, so the stored value stays current after every run - When exit code 42 + "Invalid session identifier" detected and we were attempting a resume, clear the stale cliSessionId and retry once with --resume latest (Gemini's built-in newest-file shortcut) - Suppress the 'complete' WebSocket event before the retry so the client does not receive a spurious exitCode 42 completion followed by a second stream from the successful retry
…al resume The shell/PTY path built `gemini --resume "<id>"` with no fallback, so a stale cliSessionId caused exit 42 and left the terminal stuck. Add a bash-OR chain (and PowerShell equivalent on Windows) that falls through to `--resume latest` then a fresh session, mirroring how the Claude provider already handles this.
…cover it Buffer 'invalid session identifier' stderr messages instead of forwarding them to the client immediately. On a successful retry the buffer is discarded silently; only if the retry itself fails (or no retry is possible) are the messages flushed so the client sees the real error.
a1226d2 to
392aeb3
Compare
Summary
Fixes the upstream defect where Gemini CLI assigns a new internal session ID on each run, causing all subsequent resume attempts to fail with exit code 42 and "Invalid session identifier".
Chat path (
server/gemini-cli.js)cliSessionIdin theonInithandler instead of only writing it once, so the stored value stays current after every runcliSessionId, suppress the buffered error messages, and retry once with--resume latestcompleteWebSocket event before the retry so the client doesn't receive a spurious exitCode 42 completion followed by a second streamTerminal/PTY path (
server/modules/websocket/services/shell-websocket.service.ts)gemini --resume "<id>"with no fallback, leaving the terminal stuck on a stale ID--resume <id>→--resume latest→ fresh session, with a PowerShell-compatible variant on Windows (mirroring how the Claude provider already handles this)Test plan
--resume latestfallback instead of dying with exit 42cliSessionIdis updated (future restarts should also work)Summary by CodeRabbit