createApp returns a typed BootResult. A failure is a named { ok: false, reason, detail }, and mount() renders it on the crash screen instead of leaving a blank or dead app. Every anticipated failure has a reason; a thrown failure is caught and given one too.
Quick Start
1
Handle a failed boot
mount() checks booted.ok and renders the crash screen with the detail. There is nothing to configure — a named failure always reaches the screen.2
Turn a throw into a reason
bootOrFail wraps createApp so an unanticipated throw — a StoragePort failure at settingsStore.load() — becomes the same typed shape rather than an uncaught rejection.Every BootResult.reason
unknown_engine and protocol_mismatch are the two failures selectEngine anticipates and returns as a result. storage_unavailable is different in kind: it is a throw the boot never expected, turned into the same shape by bootOrFail so it renders the same way.How a throw becomes a typed failure
createApp calls settingsStore.load() without a guard, so a StoragePort failure propagates as an exception. The chrome is already appended by the time boot runs, so an unhandled rejection would skip both the crash screen and the listener registrations — leaving a fully rendered app in which nothing happened. bootOrFail closes that gap.
Related
Architecture
Boot order and where the crash handler is installed.
Storage & Secrets
When the
StoragePort is unavailable at boot.Errors & Recovery
Failures that happen inside a turn, not at boot.
Engines
Where
unknown_engine and protocol_mismatch come from.
