Repository navigation
[iOS] Prebuilt React-Core Release artifacts are built with NSAssertions enabled — RCTAssert failures become fatal NSRangeException crashes in production #57454
Description
Activity
- addedNeeds: ReproThis issue could be improved with a clear list of steps to reproduce the issue.This issue could be improved with a clear list of steps to reproduce the issue.
on Jul 7, 2026 Warning
Missing reproducer: We could not detect a reproducible example in your issue report. Reproducers are mandatory and we can accept only one of those as a valid reproducer:
- For majority of bugs: send us a Pull Request with the RNTesterPlayground.js edited to reproduce your bug.
- If your bug is UI related: a Snack
- If your bug is build/upgrade related: a project using our Reproducer Template
You can read more about about it on our website: How to report a bug.Warning
Missing reproducer: We could not detect a reproducible example in your issue report. Reproducers are mandatory and we can accept only one of those as a valid reproducer:
- For majority of bugs: send us a Pull Request with the RNTesterPlayground.js edited to reproduce your bug.
- If your bug is UI related: a Snack
- If your bug is build/upgrade related: a project using our Reproducer Template
You can read more about about it on our website: How to report a bug.
Not applicable — the defect is in the published build artifacts themselves; the shell commands under "Steps to reproduce" demonstrate it without an app.
- addedNeeds: AttentionIssues where the author has responded to feedback.Issues where the author has responded to feedback.and removed
on Jul 7, 2026 Independent hit on this, with a trigger that has nothing to do with legacy interop — which may help with the
Needs: Reprolabel.RN 0.81.5 via Expo SDK 54, new architecture, App Store builds. Five crash reports across two app versions, three device models (iPhone 13 / 15 Pro / 17), iOS 26.5.2 and 26.6. Symbolicated against
react-native-artifacts-0.81.5-reactnative-core-dSYM-release, every one lands on the same line — the message argument, never the guarded condition:*** -[__NSArrayM objectAtIndex:]: index 13 beyond bounds [0 .. 8] -[RCTViewComponentView unmountChildComponentView:index:] (RCTViewComponentView.mm:163) RCTPerformMountInstructions(...) (RCTMountingManager.mm:97) -[RCTMountingManager performTransaction:] (RCTMountingManager.mm:258) -[RCTMountingManager initiateTransaction:] (RCTMountingManager.mm:247)Three additions to what you already have:
The artifact defect goes back further than 0.85. Same check you documented, on 0.81.5:
$ strings React.xcframework/ios-arm64/React.framework/React | grep "Attempt to unmount" Attempt to unmount a view which is mounted inside different view. (parent: %@, child: %@, index: %@) Attempt to unmount a view which has a different index. (parent: %@, child: %@, index: %@, actual index: %@, tag at index: %@)No animation loop and no interop layer here. Plain Fabric views under react-navigation + react-native-screens,
removeClippedSubviewsexplicitly false everywhere, no Reanimated layout animations. Four of the five fire from an ordinaryinitiateTransaction:on the main queue. The fifth is a pure teardown path with no user interaction at all —-[UIApplication _terminateWithStatus:]→-[RCTSurfacePresenter suspend]→_stopAllSurfacesWithScheduler:→-[RCTFabricSurface stop]→ShadowTree::commitEmptyTree(), i.e. unmount-everything at app exit. Whatever produces the index mismatch, it is reachable without any third-party view manager in the path.Symbolication note for anyone else landing here: the dSYM is published alongside the artifact as
react-native-artifacts-<version>-reactnative-core-dSYM-release.tar.gz, and its__TEXTVMA base is 0 — feedllvm-symbolizerthe raw crash offset, not0x100000000 + offset, or every frame comes back??.Opened #57865 for suggestion 2 (bounds-safe message). Suggestion 1 is the one that actually matters for apps on prebuilt artifacts, since it takes the whole assert out of production — but the message bug is worth closing regardless, because it turns any failed assert on this path into a crash rather than a log line even in debug.
- added a commit that references this issue
on Aug 13, 2026 - added a commit that references this issue
on Aug 30, 2026
Description
The prebuilt React Native Core Release artifacts published to Maven Central are built without
NS_BLOCK_ASSERTIONS, so everyRCTAssertin the framework is compiled in and live in production apps. When React Native is built from source, the standard Release configuration (ENABLE_NS_ASSERTIONS = NO) strips these asserts, so they are no-ops in production.This has two consequences:
Assert conditions that are benign in a source Release build become fatal in a prebuilt Release build. Example: in
RCTViewComponentView unmountChildComponentView:index:, theindexparameter is used only insideRCTAssert. With asserts stripped, a stale/mismatched index is harmless — the method just callsremoveFromSuperviewon the correct child. With asserts live, the same situation crashes the app.The crash is worse than an assertion failure. The assert at
RCTViewComponentView.mm(v0.85.3, L154–L177) eagerly evaluates its message arguments, including[[self.currentContainerView.subviews objectAtIndex:index] tag]. When the assert condition fails becauseindexis out of bounds, formatting the message itself throwsNSRangeException— the app dies while trying to report the assert.We hit this in production: the first release of our app on prebuilt React Native Core (RN 0.85.3) started crashing with
NSRangeExceptioninunmountChildComponentView:index:on a screen that structurally remounts children of a legacy interop view (react-native-linear-gradient2.8.3) inside an animation loop. Our previous release (RN 0.83.9, built from source) had zero crashes on the identical screen code. iOS only, observed on iOS 18 and iOS 26.Steps to reproduce
No app is needed — the defect is verifiable directly on the published artifacts:
Output (these strings only exist in the binary if the
RCTAssertcall sites were compiled in):The same check on the 0.86.0 release artifact (
react-native-artifacts-0.86.0-reactnative-core-release.tar.gz) shows the same result, so the current stable is equally affected.For comparison, a source-built Release archive of the same RN version does not contain these strings (asserts stripped by
ENABLE_NS_ASSERTIONS = NO).Production stack trace
Additional observation
Reproducing the same UI flow on a source-built Debug binary (where assertions are also enabled) does not trip the assert, while the prebuilt binary does. We have not isolated why, but it suggests the prebuilt binary may also differ behaviorally from a source build of the same version (build-time flags?). The primary, easily verifiable defect remains the assertions in the Release artifact.
Workaround
RCT_USE_PREBUILT_RNCORE=0(build React Native Core from source). Verified: the crash disappears and Release builds strip the asserts as before.Suggested fix
-releaseprebuilt artifacts withENABLE_NS_ASSERTIONS = NO/NS_BLOCK_ASSERTIONSdefined, matching what a source Release build produces.RCTViewComponentView.mmbounds-safe (it currently indexes out of bounds while formatting the message for the exact condition it is asserting against).React Native Version
0.85.3 (artifact defect also verified on 0.86.0)
Affected Platforms
Runtime: iOS. New Architecture (Fabric).
Output of
npx react-native infoReproducer
Not applicable — the defect is in the published build artifacts themselves; the shell commands under "Steps to reproduce" demonstrate it without an app.