Skip to content

fix(desktop): prevent composer busy stuck on session resume - #41907

Closed
jarv1s-csn wants to merge 1 commit into
NousResearch:mainfrom
jarv1s-csn:fix/desktop-busy-stuck-on-history-session
Closed

fix(desktop): prevent composer busy stuck on session resume#41907
jarv1s-csn wants to merge 1 commit into
NousResearch:mainfrom
jarv1s-csn:fix/desktop-busy-stuck-on-history-session

Conversation

@jarv1s-csn

@jarv1s-csn jarv1s-csn commented Jun 8, 2026

Copy link
Copy Markdown

Summary

Fix a bug where the composer send button gets permanently stuck in "running" state when clicking on a historical session in the desktop app.

Root Cause

Two interacting issues cause the stuck busy state:

  1. Race between session.info and session.resume: When resumeSession() finishes, it sets busy: false via updateSessionState. But if a session.info event with running: true fires during the resume, its RAF-scheduled flushPendingViewState() can re-apply busy: true after the resume already set it to false.

  2. No safety net: If isCurrentResume() returns false in the finally block (e.g. user navigated away mid-resume), busy is never reset.

Fix

Added a 30-second setTimeout kill switch right after setBusy(true) in resumeSession(). The timer is cleared in the finally block on normal completion. If the resume flow hangs, errors, or the isCurrentResume() guard prevents cleanup, the timer resets busy after 30 seconds — guaranteeing the composer recovers.

Test Plan

  • Click on historical session → send button should show brief loading, then return to normal
  • Navigate away quickly during resume → send button should recover within 30s
  • Click on session that was running when app was previously closed → send button should recover after resume

Related

Add a 30-second safety kill switch that resets the busy state after
session resume, preventing the composer send button from getting
permanently stuck in "running" state when:

- The gateway reports a session as running (e.g. after non-normal close)
- session.info fires during resume and re-applies busy=true via RAF
- isCurrentResume() guard blocks the finally-block cleanup

Closes NousResearch#41901
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have labels Jun 8, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary

Verdict: Approved

Analysis

Correctness

  • The fix adds a 30-second safety timeout that resets the busy state if resume stalls or navigates away. This is a reasonable defensive measure.
  • The timeout is properly cleaned up in the finally block via clearTimeout(resumeBusyTimer) when resume completes normally.

Code Quality

  • Minimal change (9 lines) with clear inline comment explaining the motivation.

Testing

  • No new tests, but this is a defensive timeout — the fix is simple enough that testing the timeout behavior would require artificial delays.

Recommendation
Approve — targeted safety fix that prevents UX stuck states.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused desktop recovery patch. This is an automated hermes-sweeper review; current main now provides the requested recovery through a broader, tested resume-state path.

  • apps/desktop/src/app/session/hooks/use-session-actions/index.ts:584-596 derives busy and awaitingResponse from the authoritative resumed.running response instead of leaving a completed resume busy.
  • apps/desktop/src/app/session/hooks/use-route-resume.ts:180-273 retries terminal resume failures with bounded backoff and exposes a manual recovery path after exhaustion.
  • Commit 93192059c96c5ba56c28c6c41255bc63af4c95fa makes the session watchdog clear the focused composer's stale busy flags, including reopened sessions whose backend state remains running. It shipped in v2026.7.1.

The PR's original file was subsequently split into apps/desktop/src/app/session/hooks/use-session-actions/index.ts, so the timer patch is also mechanically superseded.

@teknium1 teknium1 closed this Jul 14, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low — cosmetic, nice to have sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants