fix(#389): guard startup so a failure names the step instead of a blank page - #405
Open
Matobi98 wants to merge 1 commit into
Open
fix(#389): guard startup so a failure names the step instead of a blank page#405Matobi98 wants to merge 1 commit into
Matobi98 wants to merge 1 commit into
Conversation
Contributor
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Member
|
This branch conflicts with What to do on rebase:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #389. Carries the unticked half of #227: #370 fixed the specific cause (an unparseable locale), this makes startup survivable regardless of the cause.
The problem
main.dartisFuture<void> main() => bootstrapAndRun();with no guard, and the stretch ofbootstrapAndRunbeforerunAppruns seven steps. Anything that throws there meansrunAppnever runs: Flutter paints nothing, and the page is not broken — it is absent, with no message anywhere. #227 was exactly this, and finding a one-line cause took a full stack-trace hunt.Everything after
runAppalready degrades — 12catchblocks. This stretch was the outlier.The fix
Each of the seven steps was classified by what the app can still do without it.
Firebase.initializeAppRustLib.initSharedPreferencessetLoggingEnabledonBondSlashednostr_api.initializeFive of seven are optional and now log and continue through one
_optionalhelper, so a run's degradations share a[startup]prefix and read in order — which matters when one failure causes the next.The two that are not optional reach a last-resort
catchthat callsrunAppwithStartupFailureApp. That is the change in one sentence:runAppnow always runs — with the app, or with a screen saying which step failed.SharedPreferencesis a deliberate call. It could degrade to defaults, but then the app opens looking freshly installed: walkthrough again, wrong language, wallet gone. That lies about data loss in an app holding money. A screen saying "it failed while reading your settings" is better than a convincing impostor.Firebase keeps two arms rather than using the helper:
UnsupportedErroris the placeholder config, an expected state, not a failure. Collapsing both into one message would make every run log a "failed" nobody reads by the time it means something. The broadcatchbelow it is what satisfies the second acceptance criterion — a call into a third-party JS SDK can throwFirebaseException, a network error, or anything the SDK likes, and all of those escaped before.The failure surface
lib/core/startup_failure.dart. One screen: "Mostro could not start" and "It failed while <step>."No localization, no app theme, no Rust, no SharedPreferences. Any of those can be what failed, and a rescue surface that needs what broke is a second blank page. Colors are hard-coded for the same reason.
No retry button:
RustLib.initthrows when called twice, so retrying after a failure past that point would fail differently and confuse the report. Worth adding later as a real reload.The step name is the whole point. "Mostro won't open" is unactionable; "it failed loading the engine" is where to look — for the person reporting it and for whoever reads the report. Naming the step is also what the issue asks for: "a minimal error scaffold that names the failing step beats a blank page".
Platform-independent, as the issue asks: no
kIsWebanywhere in the change. Web is where it bites hardest — the in-app log viewer lives inside the app that did not start — but the guard is not web-specific.Test plan
flutter analyze— cleanflutter test— 332 passed, including 3 newcargo test/clippy/cargo check --target wasm32-unknown-unknown— clean (pre-commit hook)Manual, against the local regtest stack in Chrome, breaking each step in turn:
RustLib.initSharedPreferences[startup]lines in orderThe two failure screens saying different things is the assertion that matters — a screen that named the same step regardless would pass a careless look and be worthless.
The three new tests cover the failure screen: that it renders the step it was given, that a different step renders differently (so it cannot be ignoring the value), and that it pumps with no ProviderScope, no localization and no theme. Mutation-checked: replacing the step line with a generic message fails two of the three.
bootstrapAndRunitself is not unit-tested — reaching it needs Rust, preferences and relays, i.e. the whole app assembled to watch it not assemble. That seam is covered by the manual runs above and nothing pretends otherwise.One thing noticed while testing
Probably already known, flagging it only to confirm: with relay init broken, the app opens but the order book spins forever rather than saying it is offline. The startup guard did its job — the app opened, and Settings is reachable to switch node or edit relays — but that surface has no "disconnected" state of its own. Out of scope here; happy to open an issue if there isn't one.