React Native tvOS launch crash: a safe random-values fallback
A native call during startup can terminate a React Native process before the first component mounts. I start with the native crash report and the dependency code executed during bundle evaluation.
The available project record describes a tvOS 26.5 launch rejection caused by a throwing branch in react-native-get-random-values 2.0.0. The original rejection notice and crash log are unavailable. That record establishes the reported incident; it does not establish a failure on every device running that system version.
Preserve the random-values contract
The dependency allocates a mutable buffer and asks SecRandomCopyBytes to populate it. Its original error path throws an Objective-C NSException. The recorded failure escaped through the TurboModule C++ layer and terminated startup.
The project repair keeps the normal path and fills the same buffer with arc4random_buf if the first operation fails. This excerpt belongs inside the dependency's existing getRandomBase64 method, with its existing imports and buffer allocation:
int result = SecRandomCopyBytes(
kSecRandomDefault, byteLength, data.mutableBytes);
if (result != errSecSuccess) {
arc4random_buf(data.mutableBytes, byteLength);
}
return [data base64EncodedStringWithOptions:0];
The system arc4random_buf contract supplies cryptographic random bytes and no error return. Math.random cannot replace secure random generation. A fallback must preserve the dependency's promised output and security properties.
Persist the native change
An edit inside node_modules disappears on a clean install. The project stores patches/react-native-get-random-values+2.0.0.patch and runs patch-package from postinstall:
{
"scripts": {
"postinstall": "patch-package"
}
}
After editing the exact dependency version installed by the lockfile, generate its patch with:
npx patch-package react-native-get-random-values
Commit the resulting patch in your application repository and ensure the patch tool is available in the build environment. Check your package manager's installation hooks; Yarn modern versions and pnpm also provide native patch mechanisms.
This changes compiled native code. Rebuild and distribute a native binary. A JavaScript-only OTA cannot deliver this replacement.
Audit module-scope native access
The same repair moved DeviceInfo.getVersion() from module scope into a hook and a screen. Module-scope expressions run during module evaluation. Moving optional work delays native access until the relevant component or hook executes. The source does not establish that this precaution was required for the random-values crash.
Trace entry-point imports and follow the libraries they initialize. Read the implementation of native getters and utilities that perform work during import. Preserve initialization that a dependency explicitly requires early.
Verify the repair
I reviewed the patch and related source changes; I did not reproduce the crash on a device.
- Reinstall dependencies cleanly and inspect the native source after patch application.
- Build the affected tvOS target using release-like configuration.
- Exercise the fallback in an isolated test build and verify returned data length.
- Inspect native logs during cold launch and confirm the app reaches its first screen.
- Recheck the native implementation on dependency upgrades before retiring the patch.
Audit startup native calls and give recoverable failures a safe fallback.
References
Watch the lesson
Previous lesson: Reanimated worklet crash.
Comments