Skip to content

fix(main): guard app.on('activate') against firing before app.isReady()#326

Open
Optic00 wants to merge 1 commit into
ruzin:mainfrom
Optic00:fix/activate-before-ready
Open

fix(main): guard app.on('activate') against firing before app.isReady()#326
Optic00 wants to merge 1 commit into
ruzin:mainfrom
Optic00:fix/activate-before-ready

Conversation

@Optic00

@Optic00 Optic00 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Problem

Installed Steno.app (v0.5.8, macOS) crashed on launch with:

Uncaught Exception: Error: Cannot create BrowserWindow before app is ready
    at createWindow (main.js)
    at EventEmitter.<anonymous> (main.js)  // app.on('activate') handler

macOS can deliver the native activate event (e.g. cold launch via Dock click) before Electron's own ready event resolves. The activate handler had no app.isReady() guard - unlike the sibling second-instance and open-url handlers in the same file, which both guard on it - so it called createWindow() pre-ready and threw.

Fix

Early return from the activate handler while !app.isReady(). No queuing needed: the app.whenReady().then(...) path already creates the initial window once ready (unlike second-instance/open-url, which must preserve an incoming deep-link URL). Skipping rewarmParakeet pre-ready is fine too - the startup path does the initial warmup itself.

Verification

Deterministic repro without triggering a real crash dialog: temporarily appended app.emit('activate') at the end of main.js (after all top-level state is initialized, before whenReady() resolves) and launched via electron . with a scratch STENOAI_USER_DATA_DIR:

  • Without the guard: isReady=false, throws the exact production message Cannot create BrowserWindow before app is ready
  • With the guard: isReady=false, no throw; the window is created normally once whenReady() resolves

No e2e spec: this is a native-event timing race in the pre-ready window, not practically reachable from Playwright (the app is already past ready by the time a test can drive it).


Summary by cubic

Prevent macOS launch crash by guarding app.on('activate') until app.isReady(). Window creation now defers to the existing app.whenReady().then(...) path.

  • Bug Fixes
    • Add if (!app.isReady()) return; to the activate handler; aligns with second-instance and open-url.
    • Avoids "Cannot create BrowserWindow before app is ready" on cold Dock launch.

Written for commit 30fc88f. Summary will update on new commits.

Review in cubic

macOS can deliver 'activate' before Electron's own 'ready' event resolves
(e.g. cold launch via Dock click), which crashed with 'Cannot create
BrowserWindow before app is ready'. Mirrors the isReady() guard already
used in the second-instance/open-url handlers; app.whenReady().then()
still creates the initial window once ready.
@Optic00 Optic00 requested a review from ruzin as a code owner July 9, 2026 07:43

@cubic-dev-ai cubic-dev-ai Bot 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.

No issues found across 1 file

Not reviewed (too large): app/main.js (~6 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Re-trigger cubic

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