Skip to content

fix(desktop): a slow start gets more time and a notice, not "couldn't start" - #909

Merged
badcuban merged 1 commit into
mainfrom
fix/windows-startup-timeout
Nov 13, 2026
Merged

badcuban merged 1 commit into
mainfrom
fix/windows-startup-timeout

Conversation

@badcuban

Copy link
Copy Markdown
Collaborator

Problem

On a first start the desktop app waited 60 seconds for its backend, then killed it and showed "couldn't start", unless a database migration was visibly running. In the field that fired on Windows with the backend alive but slow: 2 of 92 installs in 30 days (5 of 540 starts), none on Mac. One start printed nothing for a minute, the next took 15 seconds to check its database and still was not ready at 60, and the third came up fine. Killing it only made the user start the same slow work again. There was also no measure of how long startup takes, so the deadline was a guess.

Fix

  • A slow start is not killed at 60 seconds. A backend still alive at the deadline, before the first window, gets a "still starting" notice (Keep Waiting / Quit) and four more minutes (SLOW_START_EXTRA_WAIT). The readiness wait in runBackendProcess now takes one deadline after another: onReadinessTimeout can answer { waitAgainFor }.
  • A stuck start still fails. When the longer wait runs out too, the run is given up on as before (kill, report, "couldn't start" dialog), and the report names the whole wait (300000 ms).
  • One notice at a time. The migration notice and the new one share a slot and live in the run's scope, so neither outlives its process. A migration found running at a deadline keeps the wait going as before and takes the notice over.
  • macOS. A message box with no parent window holds the main process there, readiness checks and timers included. The still-starting notice is waited on before the longer wait starts, so time spent behind the box does not count against the backend.
  • Startup time is reported. The first readiness of each app session sends desktop.backend.started (startupMs from a monotonic clock, attempts, slowStart) through DesktopCrashReport, under the same consent as desktop.backend.startup_failed. docs/telemetry.md lists it.

Nothing changes once the app has been ready (restarts stay quiet and unbounded) or for a backend that crashes (the three-attempt cap).

Known gap, not new: a migration found at a deadline waits with no limit. If that notice is dismissed and the backend then never answers, nothing is on screen.

Checks

  • vp fmt, vp lint, vp run typecheck, all desktop tests (385). New and changed tests in DesktopBackendManager.test.ts: a slow start that recovers and reports its time, one that never answers (notice, then failure after the full wait), one that dies under the notice, one that turns out to be migrating, and the macOS case where the box is answered late.
  • A packaged Mac app with its backend frozen (SIGSTOP) right after spawn: at 60 seconds it logged "backend alive but not ready at the readiness deadline; waiting longer", kept the backend, and showed the notice. After SIGCONT the backend answered behind it.
  • Not checked: Windows, where the notice closes itself when the backend answers (tests only), and pressing Keep Waiting on the real app (no accessibility access to click it).

… start"

On a first start the app waited 60 seconds for its backend, then killed
it and showed "couldn't start", unless a database migration was visibly
running. In the field that fired on Windows with the backend alive but
slow (2 of 92 installs in 30 days): one start printed nothing for a
minute, the next took 15 seconds to check its database, and the third
came up fine. Killing it only made the user start the same slow work
again.

A backend still alive at the deadline now gets a "still starting"
notice (Keep Waiting / Quit) and four more minutes. If that runs out
too it is given up on as before, and the report names the whole wait. A
migration found running at a deadline still keeps the wait going, and
the two notices share one slot, so only one is ever up. Where the
notice holds the app until answered (macOS), the longer wait starts
once it has been, so time spent behind the box does not count.
Nothing changes after the app has been ready once, or for a backend
that crashes.

The first start of each app session also reports how long it took
(desktop.backend.started: startupMs, attempts, slowStart), under the
same consent as the startup failure report. There was no measure of
startup time, so the deadlines were guesses.
@vercel

vercel Bot commented Nov 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadlines Ready Ready Preview Nov 13, 2026 9:37pm UTC

Request Review

@badcuban
badcuban added this pull request to the merge queue Nov 13, 2026
Merged via the queue into main with commit adbe016 Nov 13, 2026
21 checks passed
@badcuban
badcuban deleted the fix/windows-startup-timeout branch November 13, 2026 21:49

This branch was successfully deployed

1 active deployment
Preview — 9ac9cf98 Deployed Nov 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant