Skip to content

fix(desktop): survive a CLI probe candidate that throws on spawn - #793

Merged
AbirAbbas merged 2 commits into
mainfrom
fix/desktop-cli-probe-sync-throw
Jul 17, 2026
Merged

fix(desktop): survive a CLI probe candidate that throws on spawn#793
AbirAbbas merged 2 commits into
mainfrom
fix/desktop-cli-probe-sync-throw

Conversation

@AbirAbbas

Copy link
Copy Markdown
Contributor

Summary

probeCli documents itself as never rejecting, but spawn() can throw synchronously — on Windows it raises UNKNOWN when PATH resolves af to a non-PE file (concretely: launching the dev app from WSL puts the WSL Linux af binary on the interop PATH). The throw fires inside the promise executor before any listeners attach, so the promise rejects, Promise.all in probeAll rejects with it, and await initializeCli(...) kills the app.whenReady() chain before the tray or window are created. Result: electron processes running, no UI at all.

Catch the sync throw and treat that candidate as responds: false, like every other probe failure.

Validation contract

  • A candidate whose spawn throws synchronously resolves {responds: false, version: null} instead of rejecting (regression test uses spawn(''), which throws synchronously on every platform)
  • Other candidates are unaffected — startup proceeds with whichever candidates do respond

Diagnosed live: a dev launch on Windows bricked with UnhandledPromiseRejectionWarning: Error: spawn UNKNOWN at probeCli and never showed a window; with this patch applied the same launch comes up normally.

Test plan

  • npm ci, npm run typecheck, npm test — 224/224 pass
  • npm run dist:dir with stubbed vendor CLI — packages cleanly

🤖 Generated with Claude Code

spawn() can throw synchronously - on Windows it raises UNKNOWN when PATH
resolves af to a non-PE file, e.g. the WSL Linux binary seen through the
interop PATH of a dev launch. The throw happened inside probeCli's promise
executor before any listeners attached, so the promise rejected, Promise.all
in probeAll rejected with it, and app.whenReady's await initializeCli died
before the tray or window were created: the app ran headless with no UI.

Catch the throw and treat that candidate as not responding, matching
probeCli's documented never-rejects contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AbirAbbas
AbirAbbas requested a review from a team as a code owner July 17, 2026 17:09
@AbirAbbas
AbirAbbas merged commit 7784f32 into main Jul 17, 2026
15 checks passed
@AbirAbbas
AbirAbbas deleted the fix/desktop-cli-probe-sync-throw branch July 17, 2026 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant