Skip to content

Commit df86c5e

Browse files
janicduplessismeta-codesync[bot]
authored andcommitted
Fix iOS Metro reload after initial bundle failure (#58352)
Summary: If the first bundle request fails on bridgeless iOS, Metro reload does nothing — the app sits on the error screen and has to be killed and relaunched, even once the source is fixed. Android already handles this. The cause is timing. `RCTInstance` resolves the `DevSettings` TurboModule only inside `_loadJSBundle`'s success callback, and `RCTDevSettings.initialize` is what registers the Metro `reload` message handler. No successful first load means no handler, so the app never becomes a Metro reload peer. This resolves `DevSettings` at the top of `_loadJSBundle`, before the request is issued, so the handler is registered regardless of how that request turns out. The callback keeps its own resolution for the HMR setup that follows it. ## Changelog: [IOS] [FIXED] - Allow Metro reload after an initial bundle-load failure. Pull Request resolved: #58352 Test Plan: On RNTester (iOS 26.5 simulator), launched with an unresolved import so the initial bundle fails, then restored the source and waited 10 seconds: the error stayed and Metro received no bundle request, confirming the app was not a reload peer. Sending `{version: 2, method: "reload"}` to Metro then made it request a corrected bundle and recover in place, native PID `95823` unchanged. A second consecutive reload also worked. Same scenario on Android RNTester as the reference: it already receives the Metro command on the initial-error path, recovering with PID `14848` unchanged. Reviewed By: christophpurrer Differential Revision: D119072108 Pulled By: javache fbshipit-source-id: 8774564b990417cc143f55ba935b809f50eff485
1 parent 73a76dd commit df86c5e

1 file changed

Lines changed: 4 additions & 1 deletion

File tree

  • packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon

packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,10 @@ - (void)handleBundleLoadingError:(NSError *)error
537537

538538
- (void)_loadJSBundle:(NSURL *)sourceURL
539539
{
540+
// DevSettings is needed by _loadScriptFromSource's callback, so it must be initialized first. Doing it before
541+
// the request, not after a successful load, also lets Metro reload when the initial bundle request fails.
542+
[_turboModuleManager moduleForName:"DevSettings"];
543+
540544
#if RCT_DEV_MENU && __has_include(<React/RCTDevLoadingViewProtocol.h>)
541545
{
542546
id<RCTDevLoadingViewProtocol> loadingView =
@@ -569,7 +573,6 @@ - (void)_loadJSBundle:(NSURL *)sourceURL
569573
[strongSelf handleBundleLoadingError:error];
570574
return;
571575
}
572-
// DevSettings module is needed by _loadScriptFromSource's callback so prior initialization is required
573576
RCTDevSettings *const devSettings =
574577
(RCTDevSettings *)[strongSelf->_turboModuleManager moduleForName:"DevSettings"];
575578
[strongSelf _loadScriptFromSource:source];

0 commit comments

Comments
 (0)