Repository navigation
fix(startup): show a recoverable screen when Buzz fails to open or crashes - #3085
Conversation
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account, with independent Rocket, Mantis and Groot coverage.
One P3 test-gate issue: the expected bundle-404 filter also exempts unrelated console errors from the main chunk after Reload (inline). No source-demonstrated production defect found in the reviewed startup, crash, or native recovery paths.
Optional follow-ups: cover automatic completion while the slow-start Reload button owns focus, since removing the overlay can leave focus on the body; isolate the window listeners installed by each launchInit() unit-test invocation; add focused coverage for unhandled rejection, first-welcome reveal, and rejected restart. These are improvement suggestions, not additional blocking findings.
Reviewed head dd9ee533962a79175a2d3e9af71f1039ee658090, target base 3a1eb5601e997811009d01601786df8af9393a7f, feature merge-base 40e6ccb597cf9d8b47f9692de8285458cc304017. Source-only: no tests, builds, or apps executed by reviewers. One-time hosted check snapshot reports CI required passing; Windows native validation skipped. Native restart/reveal and screen-reader behavior remain unexercised. Inspected the description and all nine screenshots; the three videos were not inspected.
If the app bundle failed to load, createServices() threw, or App threw before marking the launch ready, the window stayed on the looping "Opening Buzz" mark with #root empty and inert, and screen readers heard only "Opening Buzz". An uncaught render error after launch left an empty window. Nothing caught any of these. - launch-init.js, which needs nothing from the bundle, now renders the fallback in plain DOM: "Buzz couldn’t open" / "Something went wrong while starting. Your messages and settings are safe." [Reload], plus [Restart Buzz] on the desktop through the native restart, and the error in a collapsed Details. It removes the launch, hides the app roots, shows a still-hidden first-welcome Mac window, and focuses Reload. - It installs global error (including failed script loads) and unhandledrejection listeners that fail startup until React has the app, then leave other errors to the running app. - main.tsx (FOUNDATION, edited on the user's explicit instruction) wraps startup in try/catch and passes createRoot an onUncaughtError, both of which show the fallback through src/app/launch.ts, and tells launch-init.js once React has the app. - A watchdog adds "This is taking longer than usual." [Reload] to the launch after 20 seconds; the launch still leaves by itself if it ends. - Style both with design tokens in startup.css, which now also loads the typography roles it uses. - Browser journeys in both engines cover a bundle that doesn't load, Restart Buzz, a throwing createServices() and App (via a fixture build), and the slow launch under a controlled clock. Unit tests cover the fallback, its listeners and the watchdog. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: mtoohey <[email protected]> (cherry picked from commit bfd8001fb84967696325c1460ccb9e2cdab20f52) Signed-off-by: Matt Toohey <[email protected]>
…shes React reports an error no boundary caught through the root's onUncaughtError, which shows launch-init.js's fallback page. That page always said "Buzz couldn’t open … while starting", even when the user had been using Buzz for hours. Once React has the app and the launch screen is gone, the page now says "Buzz stopped working" / "Something went wrong. Your messages and settings are safe.", with the same Reload, Restart Buzz and Details. Startup failures keep "Buzz couldn’t open". The startup-failure fixture build gains a "running" seam in the app's content, which throws on the next navigation, so a browser journey can crash the app after it opened. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: mtoohey <[email protected]> (cherry picked from commit 76eb5aca896c3ab27668fe16e176808574592066) Signed-off-by: Matt Toohey <[email protected]>
The bundle-load journeys declared `expectedStartupFailure: "/assets/index-"`, and the fixture excused any console error whose text or source location contained that string. After Reload the recovered app runs from that same chunk, so an unrelated error it logged, or any Error whose stack named the chunk, passed the no-errors gate. Split the option. `expectedStartupFailure` keeps matching an injected exception's message. New `expectedStartupLoadFailure` names a resource that fails to load: the fixture records each failed response to a URL containing it, and excuses only that response's own "Failed to load resource" error, once, by exact URL and status, as the injected 403/404 matchers already do. A control journey that crashed the app after Reload now fails the gate with the chunk's error; the six startup journeys pass in Chromium and WebKit. Signed-off-by: Matt Toohey <[email protected]> Co-Authored-By: Claude Fable 5.1 <[email protected]>
dd9ee53 to
a4672ad
Compare
kazemek21
left a comment
There was a problem hiding this comment.
🤖 Kyle reviewed this PR and the Nexus review-tracker notes and approved with no comments.
Posted by Codex (gpt-6.1-sol) on behalf of kylez
…restricted-communities * origin/main: ci: give WebKit shards headroom and keep fixture servers' idle connections open (#3074) fix(messages): offer Retry as soon as a send fails (#3080) fix(agents): link Settings from key failures and quote the provider (#3081) fix(identity): link Builderlab from Identity sync where its page holds the next step (#3082) fix(startup): show a recoverable screen when Buzz fails to open or crashes (#3085) fix(attention): ask before deleting a watch (#3092) fix(agents): remove the owner-access read tools (#3123) fix(channels): keep the side pane mounted under the image viewer (#3111) fix(solo): ask before Escape or Close drops a new workspace's typed fields (#3114) # Conflicts: # docs/configuration.md # vite.config.ts
Summary
Part 2 of 3 from the
errors-3work (DA-12). When Buzz cannot finish opening, the window today stays on the looping "Opening Buzz" mark with nothing a person can do; when the running app hits a React error no boundary catches, the window goes blank. Screen readers hear only "Opening Buzz". This PR adds a recoverable fallback that needs nothing from the app bundle: Buzz couldn’t open for startup failures, Buzz stopped working for a crash after launch, each with Reload, Restart Buzz on the desktop, and the error behind a collapsed Details. A start that takes more than 20 seconds says This is taking longer than usual. and offers Reload while still opening by itself if it finishes.Changes
1c6351d09fix(startup): DA-12 show "Buzz couldn’t open" when startup failsdd9ee5339fix(startup): DA-12 say "Buzz stopped working" when a running app crashesMechanisms:
public/launch-init.js: builds the page with plain DOM and the tokensstartup.cssalready loads, removes the launch, hides and inerts#rootand#buzz-toast-root, reveals a still-hidden first-welcome Mac window, and focuses Reload. Later failures append to Details.error/unhandledrejectionlisteners inlaunch-init.js(capture phase, so a failed<script>load counts) that fail startup until React has the app, then leave other errors to the running app.src/main.tsxaroundcreateServices()and the first render, reporting throughshowStartupFailure()insrc/app/launch.ts;startupHandedToReact()tellslaunch-init.jsonce React has the app.onUncaughtErroroncreateRoot: an error no boundary caught reaches the same fallback with the component stack in Details.startupFailureFixturebuild option (tests/browser/build.mjs) that throws wherewindow.__buzzFixtureStartupFailuresays (services,render,running), andexpectedStartupFailureintests/browser/fixture.mjsso a journey's injected failure passes the console/page-error gate.docs/buzz-help.mddescribes the behaviour.Evidence
Headless Chromium 1280×800, light theme,
launchAnimation: true, driven bytests/browser/fixture.mjs. Before is the merge base40e6ccb597with only this branch's test infra applied; After is this branch.1. Main bundle fails to load (desktop), at 15 s
2. The same, with Details expanded
3.
createServices()throws (storage unavailable), at 15 s4.
Appthrows during its first render5. Watchdog: the bundle is held, at 20 s
6. Crash after launch (the app's content throws on the next navigation)
7. Browser build (no Tauri stub): Reload only
8. Screen-reader view (Playwright aria snapshot)
Text of the same snapshots, from
page.locator("body").ariaSnapshot()with the bundle failing to load (desktop stub):Before (the same in every scenario above, except the crash after launch, where the body has no accessible nodes at all):
After:
After, slow launch at 20 s (the launch is a status region, so the added text is read when it appears):
After, crash after launch:
9. Reload with the bundle restored
Videos
Same scripted steps in both builds: open with the bundle failing, wait 20 s (sped up 8× with a caption saying so), restore the bundle, then click Reload where there is one. Captions are in a band under the content.
Before
before.mp4
After
after.mp4
Side by side
side-by-side.mp4
Testing
Run in the PR worktree at
dd9ee5339:Not run here:
just scan, the native build, and a human test in the desktop app (Restart Buzz is exercised only through a__TAURI_INTERNALS__stub).Notes
src/main.tsxis a FOUNDATION file. It was changed on explicit human instruction: startup is wrapped in try/catch,createRootgetsonUncaughtError, andstartupHandedToReact()runs after the first render. Please give it the stricter review.🤖 Generated with Claude Code