Skip to content

fix(desktop): persist zoom to JSON, save window state on show, auto-relaunch --no-sandbox on Windows crash loop - #57414

Closed
Sahil-SS9 wants to merge 1 commit into
NousResearch:mainfrom
Sahil-SS9:fix/issue-56726-windows-desktop-crash-zoom
Closed

fix(desktop): persist zoom to JSON, save window state on show, auto-relaunch --no-sandbox on Windows crash loop#57414
Sahil-SS9 wants to merge 1 commit into
NousResearch:mainfrom
Sahil-SS9:fix/issue-56726-windows-desktop-crash-zoom

Conversation

@Sahil-SS9

Copy link
Copy Markdown
Contributor

Fixes #56726

Description

The Hermes desktop app on Windows was failing to open correctly due to three issues reported in #56726:

  1. Renderer sandbox crash loop → dead black screen. On certain Windows setups, the Chromium/Electron renderer sandbox crashes deterministically on startup. The existing crash-loop suppression (3 crashes in 60s → stop reloading) left the user with a dead window and no recovery path. This PR adds a one-shot auto-relaunch with --no-sandbox when a crash loop is detected on Windows, so the user gets a working window instead of an unusable app. The relaunch is gated by a one-shot flag to prevent infinite loops if --no-sandbox doesn't help.

  2. Zoom level resets after crash recovery. Zoom was persisted only in the renderer's localStorage, which lives under Electron/Chromium cache storage. During crash recovery, these folders may be moved or recreated, wiping the zoom value. This PR adds a main-process JSON file (zoom-state.json) as the primary zoom store, with localStorage kept as a secondary mirror for backward compatibility. restorePersistedZoomLevel now prefers the JSON file and falls back to localStorage.

  3. Window geometry lost if app crashes before first resize/move/close. Window state was only persisted on resize, move, maximize, unmaximize, and close events. If the app crashed before any of those fired, window-state.json was never written. This PR adds a schedulePersistWindowState() call in the ready-to-show handler so the restored bounds are captured as soon as the window is visible.

Verification

  • node -c apps/desktop/electron/main.cjs — syntax check passes
  • node --test apps/desktop/electron/window-state.test.cjs — 15/15 pass
  • node --test apps/desktop/electron/bootstrap-platform.test.cjs — 10/10 pass
  • node --test apps/desktop/electron/hardening.test.cjs apps/desktop/electron/update-relaunch.test.cjs apps/desktop/electron/session-windows.test.cjs — 42/42 pass
  • Quality gates: S1 (secrets) clean, S2 (personal refs) clean, C1 (conventional commits) clean, F1 (focused diff — only main.cjs changed)

@alt-glitch alt-glitch added type/bug Something isn't working comp/desktop Electron desktop app (apps/desktop/*) platform/windows Native Windows-specific behavior or breakage P2 Medium — degraded but workaround exists sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows labels Jul 3, 2026
@Sahil-SS9
Sahil-SS9 force-pushed the fix/issue-56726-windows-desktop-crash-zoom branch from 23bf322 to 352d289 Compare July 9, 2026 07:35
@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
teknium1 added a commit that referenced this pull request Jul 18, 2026
…sandbox loss

Follow-up to the salvaged #66803 (@HexLab98):

- Two-strike boot marker: a single mid-boot abort (task-manager kill,
  power loss) no longer disables the sandbox — only a second consecutive
  abort, or a signature-confirmed GPU/renderer STATUS_BREAKPOINT death,
  engages --no-sandbox.
- Version-scoped stickiness: the fallback marker records the app version
  and re-probes the sandbox once after an update (new Electron or
  installer ACL repair may have fixed the host) instead of degrading
  forever. A failed re-probe returns straight to fallback.
- Launch-time icacls repair now runs only when the marker shows a prior
  aborted boot (icacls /T recurses the whole install tree — healthy
  launches skip it; the installer grants the ACE at install time), and
  targets the install dir only. The userData grant is dropped: granting
  S-1-15-2-2 RX on userData would expose Hermes sessions/config to every
  AppContainer app on the machine.
- Renderer crash-loop recovery (same class as #56726, credit @Sahil-SS9
  in PR #57414): a Windows renderer crash loop bearing the breakpoint
  exit code gets the same one-shot --no-sandbox relaunch instead of a
  dead window; unrelated crash loops keep the sandbox.
- Manual --no-sandbox launches are honored but never made sticky.

Tests: 15/15 windows-sandbox-fallback vitest; full desktop electron
suite 432 passed / 1 skipped.
teknium1 pushed a commit that referenced this pull request Jul 18, 2026
#56726)

Surgical reapply of the surviving halves of PR #57414 by @Sahil-SS9
(the branch predates the ts-ify migration and the zoom apply/notify
funnel, so a direct cherry-pick no longer applies):

- Zoom persists to a main-process zoom-state.json as the primary store.
  The old localStorage-only store lives under Electron's cache/storage
  folders, which crash recovery can move or recreate — wiping zoom
  exactly when the user recovers from a crash. localStorage stays as a
  secondary mirror; pre-JSON installs migrate on first read.
- Window geometry persists at ready-to-show, so a crash before the
  first resize/move/close still captures the restored bounds.

The third half of #57414 (one-shot --no-sandbox relaunch on Windows
renderer crash loops) was superseded by #66842, which ships the same
recovery gated on the 0x80000003 sandbox-crash signature.

Adapted to current main: restore/persist route through the
applyZoomLevel funnel (39230d1) so the settings UI Scale control
stays in sync, and JSON writes go through writeFileAtomic.
@teknium1

Copy link
Copy Markdown
Contributor

Merged via PR #66901 (#66901) — your zoom-persistence and window-state-on-show fixes are on main with your authorship preserved via rebase-merge. Thanks for the solid root-cause analysis on the localStorage/cache-folder interaction!

Your branch predated the desktop ts-ify migration and the zoom apply/notify funnel, so the changes were surgically reapplied onto current main under your authorship rather than cherry-picked: restore/persist now route through applyZoomLevel (keeps the settings Scale control in sync) and the JSON writes use writeFileAtomic.

The third part of this PR — the one-shot --no-sandbox relaunch on Windows renderer crash loops — was superseded by PR #66842 (see #38216), which ships the same recovery gated on the 0x80000003 sandbox-crash signature so unrelated crash loops keep the sandbox. You're credited there as the first to ship the relaunch approach.

Closing this PR in favor of the merged salvage. Thanks again!

@teknium1 teknium1 closed this Jul 18, 2026
@Sahil-SS9
Sahil-SS9 deleted the fix/issue-56726-windows-desktop-crash-zoom branch July 19, 2026 08:01
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…sandbox loss

Follow-up to the salvaged NousResearch#66803 (@HexLab98):

- Two-strike boot marker: a single mid-boot abort (task-manager kill,
  power loss) no longer disables the sandbox — only a second consecutive
  abort, or a signature-confirmed GPU/renderer STATUS_BREAKPOINT death,
  engages --no-sandbox.
- Version-scoped stickiness: the fallback marker records the app version
  and re-probes the sandbox once after an update (new Electron or
  installer ACL repair may have fixed the host) instead of degrading
  forever. A failed re-probe returns straight to fallback.
- Launch-time icacls repair now runs only when the marker shows a prior
  aborted boot (icacls /T recurses the whole install tree — healthy
  launches skip it; the installer grants the ACE at install time), and
  targets the install dir only. The userData grant is dropped: granting
  S-1-15-2-2 RX on userData would expose Hermes sessions/config to every
  AppContainer app on the machine.
- Renderer crash-loop recovery (same class as NousResearch#56726, credit @Sahil-SS9
  in PR NousResearch#57414): a Windows renderer crash loop bearing the breakpoint
  exit code gets the same one-shot --no-sandbox relaunch instead of a
  dead window; unrelated crash loops keep the sandbox.
- Manual --no-sandbox launches are honored but never made sticky.

Tests: 15/15 windows-sandbox-fallback vitest; full desktop electron
suite 432 passed / 1 skipped.
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
NousResearch#56726)

Surgical reapply of the surviving halves of PR NousResearch#57414 by @Sahil-SS9
(the branch predates the ts-ify migration and the zoom apply/notify
funnel, so a direct cherry-pick no longer applies):

- Zoom persists to a main-process zoom-state.json as the primary store.
  The old localStorage-only store lives under Electron's cache/storage
  folders, which crash recovery can move or recreate — wiping zoom
  exactly when the user recovers from a crash. localStorage stays as a
  secondary mirror; pre-JSON installs migrate on first read.
- Window geometry persists at ready-to-show, so a crash before the
  first resize/move/close still captures the restored bounds.

The third half of NousResearch#57414 (one-shot --no-sandbox relaunch on Windows
renderer crash loops) was superseded by NousResearch#66842, which ships the same
recovery gated on the 0x80000003 sandbox-crash signature.

Adapted to current main: restore/persist route through the
applyZoomLevel funnel (e90478b) so the settings UI Scale control
stays in sync, and JSON writes go through writeFileAtomic.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) P2 Medium — degraded but workaround exists platform/windows Native Windows-specific behavior or breakage sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hermes Desktop app on Windows would not open correctly

3 participants