Skip to content

Fix iOS Metro reload after initial bundle failure - #58352

Closed
janicduplessis wants to merge 7 commits into
react:mainfrom
janicduplessis:@janic/ios-simulator-reload
Closed

Fix iOS Metro reload after initial bundle failure#58352
janicduplessis wants to merge 7 commits into
react:mainfrom
janicduplessis:@janic/ios-simulator-reload

Conversation

@janicduplessis

@janicduplessis janicduplessis commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

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.

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.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 4, 2026
@facebook-github-tools facebook-github-tools Bot added Contributor A React Native contributor. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Sep 4, 2026
@meta-codesync

meta-codesync Bot commented Sep 7, 2026

Copy link
Copy Markdown

@javache has imported this pull request. If you are a Meta employee, you can view this in D119072108.

@meta-codesync meta-codesync Bot closed this in df86c5e Sep 9, 2026
@meta-codesync meta-codesync Bot added the Merged This PR has been merged. label Sep 9, 2026
@meta-codesync

meta-codesync Bot commented Sep 9, 2026

Copy link
Copy Markdown

@javache merged this pull request in df86c5e.

shashikant-panchal pushed a commit to shashikant-panchal/react-native that referenced this pull request Sep 10, 2026
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: react#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. Merged This PR has been merged. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant