CarPlay voice-based-conversational app crashes when CarPlay scene activates before phone scene (React Native + Expo)

Hi all,

I'm building a CarPlay app for the voice-based-conversational category (entitlement approved March 2026), and I've hit a crash I can't resolve through public documentation. Hoping someone here has seen this.

Setup

  • App: React Native via Expo SDK 54 (RN 0.81)
  • CarPlay library: react-native-carplay@2.4.1-beta.0
  • iOS: 26.4.2
  • Entitlement: com.apple.developer.carplay-voice-based-conversation
  • Architecture: ExpoAppDelegate subclass with two scene delegates declared in UIApplicationSceneManifest:
    • PhoneSceneDelegate (UIWindowSceneDelegate)
    • CarSceneDelegate (CPTemplateApplicationSceneDelegate)

What works

iPhone app launched first, CarPlay connects after: no crash. Placeholder CPListTemplate titled "Enough" displays. templateApplicationScene(_:didConnect:) is called. However the React Native side never receives the didConnect event from RNCarPlay — the placeholder is the only thing that ever shows. JS never gets a chance to call setRootTemplate(VoiceControlTemplate).

What fails

When CarPlay is the first scene to activate (iPhone app not running, user opens the app icon directly on the head unit), the app crashes immediately:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000190932800
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Triggered by Thread:  0

Thread 0 Crashed:
0   libswiftCore.dylib   _assertionFailure(...)   AssertCommon.swift:171
1-5 Enough               (our Swift code, in CarSceneDelegate path)
6   libdispatch.dylib    _dispatch_call_block_and_release

Thread 11 (in parallel):
hermes   evaluatePreparedJavaScript
React    ReactInstance::loadScript
React    RCTJSThreadManager runRunLoop

So React Native is bootstrapping on Thread 11 (Hermes loading the bundle), but Thread 0 fires a Swift assertion in our code path immediately after factory.startReactNative(...).

What we've tried

~16 builds with iterative hypotheses. Two key ones:

Passing UIWindow(frame: UIScreen.main.bounds) to factory.startReactNative(in:): crashes because iOS 13+ requires every UIWindow to belong to a UIWindowScene, and we were creating one without scene association.

Passing nil to factory.startReactNative(in:): the header RCTReactNativeFactory.h declares inWindow:(UIWindow *_Nullable)window, so nil should be valid. But the crash signature is identical — Swift assertion failure inside ExpoReactNativeFactory or RCTReactNativeFactory. Looks like an internal precondition that requires window != nil despite the header.

Other hypotheses ruled out: linker stripping of scene delegate classes (verified with nm), wrong protocol method signature (we use didConnect: for voice-based-conversational, not didConnect:to: which is for navigation apps), AppDelegate vs SceneDelegate bootstrap conflict.

One hypothesis we haven't tested: bootstrapping React Native fully in application:didFinishLaunchingWithOptions: before any scene activates, exposing the bridge via singleton. This is the pattern documented in RN issue #41777 and the Adapptor blog (2022). We haven't tried because ExpoReactNativeFactory is more opaque than the older RCTAppDelegate and we're unsure which internal initialization steps are safe to extract.

Specific questions

  1. Is RCTReactNativeFactory.startReactNative(withModuleName:in:launchOptions:) actually supported with nil window? The _Nullable annotation suggests yes, but runtime says no. Is the annotation aspirational or am I missing a setup step?

  2. For React Native apps using voice-based-conversational, is there a recommended pattern to handle CarPlay-first launch? All public documentation I've found is either for legacy CPApplicationDelegate or for navigation apps with MapTemplate.

  3. Can VoiceControlTemplate be presented from native Swift without involving the JS bridge for the initial template? This would let us avoid the bridge bootstrap problem on the CarPlay scene path.

Any insights, war stories, or pointers to documentation I might have missed would be hugely appreciated. Multi-week investigation here and I'd love to find the right pattern or confirm an upstream issue worth filing as feedback.

Thanks!

CarPlay voice-based-conversational app crashes when CarPlay scene activates before phone scene (React Native + Expo)
 
 
Q