Skip to content

fix(desktop): sync $activeSessionId atom after session-recovery auto-retry - #62471

Closed
luxles wants to merge 1 commit into
NousResearch:mainfrom
luxles:fix/desktop-session-recovery-atom-update
Closed

fix(desktop): sync $activeSessionId atom after session-recovery auto-retry#62471
luxles wants to merge 1 commit into
NousResearch:mainfrom
luxles:fix/desktop-session-recovery-atom-update

Conversation

@luxles

@luxles luxles commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Problem

When prompt.submit returns "session not found" (stale runtime session ID after Gateway restart, WS orphan reap, or context compression), the frontend auto-recovers by calling session.resume to get a fresh runtime ID, then retries the submit.

However, the recovery only updates activeSessionIdRef.current (a ref) without calling setActiveSessionId() (the React atom).

The next submitPrompt call gets sessionId from useStore($activeSessionId) — the atom, which still holds the old stale runtime ID. So every other message fails with "session not found", creating a retry loop.

Fix

Add setActiveSessionId(recoveredId) on the recovery path alongside the ref update.

File: apps/desktop/src/app/session/hooks/use-prompt-actions.ts

Related Issues

Fixes #51058
Related: #38704, #44183, #47709

@alt-glitch alt-glitch added type/bug Something isn't working comp/desktop Electron desktop app (apps/desktop/*) sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state P2 Medium — degraded but workaround exists labels Jul 11, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for identifying the atom/ref divergence; the premise remains valid on current main.

Problems

  • The submitted diff changes apps/desktop/src/app/session/hooks/use-prompt-actions.ts, but the live retry branch was extracted by 7337248a4c182d65b6c101acac1e21be5101c4cc and now lives at apps/desktop/src/app/session/hooks/use-prompt-actions/submit.ts:298-309. The current branch still only writes activeSessionIdRef.current at submit.ts:306, so the fix must be transplanted there.
  • The same ref-only recovery pattern also appears in submit.ts:226-233 and index.ts:548-557; please keep the atom and ref synchronized across these current recovery paths.
  • index.test.tsx:1050-1095 verifies the retry RPC sequence but not $activeSessionId; add a regression assertion for the recovered atom value and a subsequent submit.

Suggested changes

  • Import and call setActiveSessionId(recoveredId) beside the current ref updates, then extend the existing recovery test.

Automated hermes-sweeper review.

@@ -505,6 +506,7 @@ export function usePromptActions({
const recoveredId = resumed?.session_id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the correct state transition, but current main extracted this retry branch to apps/desktop/src/app/session/hooks/use-prompt-actions/submit.ts:298-309 (commit 7337248a4c182d65b6c101acac1e21be5101c4cc). Please transplant the atom update there; this file is no longer the live implementation.

@teknium1 teknium1 added the sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform label Jul 11, 2026
@luxles
luxles force-pushed the fix/desktop-session-recovery-atom-update branch from a52360e to 5bd5909 Compare July 14, 2026 08:39
@luxles

luxles commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Updated per review feedback

Rebased on latest main and transplanted the fix to the refactored file structure:

Fixed 2 recovery paths:

  • submit.ts:368setActiveSessionId(recoveredId) added before the retry submit
  • index.ts:559setActiveSessionId(recoveredId) added before the interrupt retry

Added regression tests:

  • index.test.tsx — asserts $activeSessionId.get() === RECOVERED_SESSION_ID after both prompt.submit and session.interrupt recovery paths

cc @teknium1

@OutThisLife

Copy link
Copy Markdown
Collaborator

Superseded by #81261.

Thanks for this — the $activeSessionId desync after recovery is carried over there, with you credited via Co-authored-by.

Consolidating because this is one bug class across several PRs: main had three hand-rolled copies of the same stale-session recovery (prompt.submit, session.interrupt, session.redirect), and the RPCs that never got a copy — attach, /compress, checkpoint restore, tile actions — each failed the same way. #81261 makes it one resolver and routes every path through it, so the next session-scoped RPC we add inherits the fix instead of needing a fourth copy.

@OutThisLife OutThisLife closed this Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/desktop Electron desktop app (apps/desktop/*) P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI/Desktop session mix-up after context compression / reconnect resumes the wrong chat

4 participants