Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

[iOS] Prebuilt React-Core Release artifacts are built with NSAssertions enabled — RCTAssert failures become fatal NSRangeException crashes in production

Aberta
#57,454 3 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
4/5
Tempo estimado
3-5 dias
Facilidade para iniciantes
52/100
Tipo de issue
Bug
Clareza
Razoavelmente clara
Status de atividade
Pouca atividade
Stack de tecnologia
ios, objective-c, react-native
Domínio
build-system, mobile

Direção de pesquisa

Comece com RCTViewComponentView.mm e a configuração de build dos artefatos de release; compare o arquivo 0.85.3 ou 0.86.0 publicado com um arquivo Release compilado a partir do código-fonte. Execute os comandos curl, tar e strings da issue para verificar os símbolos de assertion e, em seguida, confirme que os artefatos de release não os contêm mais e que a mensagem de assert não indexa além dos limites de subviews.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

Needs: Attention Needs: Repro

Description

The prebuilt React Native Core Release artifacts published to Maven Central are built without NS_BLOCK_ASSERTIONS, so every RCTAssert in 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:

  1. Assert conditions that are benign in a source Release build become fatal in a prebuilt Release build. Example: in RCTViewComponentView unmountChildComponentView:index:, the index parameter is used only inside RCTAssert. With asserts stripped, a stale/mismatched index is harmless — the method just calls removeFromSuperview on the correct child. With asserts live, the same situation crashes the app.

  2. 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 because index is out of bounds, formatting the message itself throws NSRangeException — 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 NSRangeException in unmountChildComponentView:index: on a screen that structurally remounts children of a legacy interop view (react-native-linear-gradient 2.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:

# RN 0.85.3 release artifact
curl -sL https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.85.3/react-native-artifacts-0.85.3-reactnative-core-release.tar.gz | tar -xz
strings React.xcframework/ios-arm64/React.framework/React | grep "Attempt to unmount"

Output (these strings only exist in the binary if the RCTAssert call sites were compiled in):

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: %@)

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

NSRangeException: *** -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]
  CoreFoundation   __exceptionPreprocess
  libobjc.A        objc_exception_throw
  CoreFoundation   -[__NSSingleObjectArrayI objectAtIndex:]
  React            -[RCTViewComponentView unmountChildComponentView:index:]
  React            -[RCTMountingManager performTransaction:] (block)
  React            facebook::react::TelemetryController::pullTransaction
  React            -[RCTMountingManager performTransaction:]
  React            -[RCTMountingManager initiateTransaction:]
  libdispatch      _dispatch_main_queue_drain
  ...

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

  1. Build the -release prebuilt artifacts with ENABLE_NS_ASSERTIONS = NO / NS_BLOCK_ASSERTIONS defined, matching what a source Release build produces.
  2. Independently: make the assert message at RCTViewComponentView.mm bounds-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 info

System:
  OS: macOS 26.5.1
  CPU: (12) arm64 Apple M2 Pro
Binaries:
  Node: 24.14.0
  Yarn: 4.16.0
  npm: 11.9.0
  Watchman: 2025.06.30.00
SDKs:
  iOS SDK: 26.5
Xcode: 26.6/17F113
Ruby: 3.3.10
react-native: 0.85.3
Hermes: enabled
New Architecture: enabled

Reproducer

Not applicable — the defect is in the published build artifacts themselves; the shell commands under "Steps to reproduce" demonstrate it without an app.

Linguagem predominante
C++
Estrelas
127k
Forks
25.3k
Métricas de merge de PRs
Nenhum PR com merge em 30d

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de react/react-native

Todas as issues de react/react-native

Issues semelhantes

Mais issues de C++

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.