# App launches without crashing on supported OS versions

- **Pattern:** `ab-000493` (`app-store-review-blockers.completeness-stability.no-crash-on-launch`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000493
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000493)

## Why it matters

A crash on launch is the highest-severity rejection — the reviewer cannot evaluate any other part of the app. Apple tests on multiple OS versions and device types; an unhandled exception in root initialization code (unguarded `useEffect`, top-level `JSON.parse`, missing optional chaining) will crash on at least one configuration. CWE-390 (detection of error condition without action) and ISO 25010:2011 fault-tolerance both classify this as a fundamental reliability failure. One uncaught rejection in a startup async chain means the entire binary is rejected.

## Severity rationale

Critical because a launch crash makes the app completely unreviable — no functionality can be evaluated and rejection is immediate.

## Remediation

Add a root error boundary in `App.tsx` and wrap all startup async operations in try/catch.

```tsx
// App.tsx
import { ErrorBoundary } from 'react-error-boundary';

export default function App() {
  return (
    <ErrorBoundary FallbackComponent={({ error }) => (
      <View><Text>Something went wrong. Please restart the app.</Text></View>
    )}>
      <NavigationContainer>
        <RootNavigator />
      </NavigationContainer>
    </ErrorBoundary>
  );
}
```

For startup data fetching, always add a `catch` block: `useEffect(() => { fetchConfig().catch(console.error); }, [])`. Test launch on the minimum supported OS version using Simulator (iOS) or AVD (Android) before every submission.

## Detection

- **ID:** `no-crash-on-launch`
- **Severity:** `critical`
- **What to look for:** Count all relevant instances and enumerate each. Look for crash-causing patterns in the app entry point and early initialization code: unhandled promise rejections in `useEffect` on the root component; missing null checks on environment variables that are expected at startup; synchronous throws in module-level code (top-level `JSON.parse()` without try/catch, optional chaining missing on potentially undefined values); missing error boundaries at the root level. Check `App.tsx` (React Native/Expo), `main.dart` (Flutter), `AppDelegate.swift` (iOS), or `MainActivity.kt` (Android) for try/catch coverage of critical initialization. Also search for known crash-inducing patterns: calling `navigation.navigate()` before the navigator is ready, accessing `AsyncStorage` synchronously, or using deprecated APIs removed in the minimum supported OS version.
- **Pass criteria:** The app entry point and initialization sequence have error handling. At least 1 implementation must be verified. A root-level `ErrorBoundary` (React Native) or equivalent (Flutter `ErrorWidget.builder`, iOS `NSSetUncaughtExceptionHandler`) is present to catch unexpected crashes gracefully.
- **Fail criteria:** Missing error boundary at the root level; synchronous throws in module initialization; unhandled rejections on startup async operations; use of APIs deprecated or removed in the minimum supported OS.
- **Skip (N/A) when:** Never — launch stability is always required.
- **Detail on fail:** `"No root ErrorBoundary found — any uncaught exception will crash the app on launch"` or `"App.tsx has unhandled async initialization in useEffect with no catch block"`
- **Remediation:** Apple's review process runs your app on multiple OS versions and device types. Protect launch:
  1. Add a root error boundary in React Native:
     ```tsx
     // App.tsx
     import { ErrorBoundary } from 'react-error-boundary';
     export default function App() {
       return (
         <ErrorBoundary FallbackComponent={ErrorFallback}>
           <NavigationContainer>...</NavigationContainer>
         </ErrorBoundary>
       );
     }
     ```
  2. Wrap all startup `useEffect` async operations in try/catch
  3. Use optional chaining (`?.`) and nullish coalescing (`??`) defensively on all external data at startup
  4. Test launch on the minimum supported OS version using Simulator (iOS) or AVD (Android)

## External references

- cwe CWE-390
- iso-25010 fault-tolerance

Taxons: error-resilience, regulatory-conformance

HTML version: https://auditbuffet.com/patterns/ab-000493
