Skip to content

Commit cecd11e

Browse files
shubhamksavitafacebook-github-bot
authored andcommitted
Handle missing viewState gracefully in SurfaceMountingManager.updateState and updatePadding (#57181)
Summary: ## Summary Fixes `RetryableMountingLayerException: Unable to find viewState for tag N. Surface stopped: false` crashing `com.oculus.firsttimenux` from the Fabric batch-mount path. Logview link: [252c85116a7ab5c4ec93ef3c3373cf9d](https://www.internalfb.com/logview/system_vros_crashes/252c85116a7ab5c4ec93ef3c3373cf9d) ## Root cause `IntBufferBatchMountItem.execute` dispatches batched mount instructions. When a view tag is transiently missing from the registry (async race between the JS commit and native mount — surface teardown / out-of-order delivery), mount methods that call the throwing `getViewState` raise `RetryableMountingLayerException`. `MountItemDispatcher.dispatchMountItems` only retries this exception `if (item is DispatchCommandMountItem)` (comment: *"Only DispatchCommandMountItem supports retries"*) — `IntBufferBatchMountItem` is not one, so the "retryable" exception propagates uncaught and crashes the app. The RN team has been hardening each batch mount method to handle missing viewState gracefully (soft-log + early return): `addViewAt` in `D99760257` (which references this same MID and process), `updateOverflowInset` in `D104400233`; `removeViewAt`, `updateProps`, `updateLayout`, and `deleteView` were already graceful. The originally-reported `addViewAt` stack is therefore already fixed in trunk — crashes persist on release branch v201/v203 which predates `D99760257`. `updateState` (`INSTRUCTION_UPDATE_STATE`) and `updatePadding` (`INSTRUCTION_UPDATE_PADDING`) were the two remaining throwing `getViewState` callers reachable from `IntBufferBatchMountItem.execute` — unfixed siblings of the same multi-site pattern and live/contributing crash sites for the same exception. ## Fix Change `updateState` and `updatePadding` to use `getNullableViewState`; on null, log a `SURFACE_MOUNTING_MANAGER_MISSING_VIEWSTATE` soft exception and return early — identical to the established pattern in `addViewAt`, `updateOverflowInset`, `updateProps`, `updateLayout`, and `deleteView`. This is not a throw-downgrade of an invariant: `RetryableMountingLayerException` is an explicitly retryable transient signal, and this matches the canonical handling the RN team applies to every other batch mount method. The non-batch callers (`sendAccessibilityEvent`, `setJSResponder`) are intentionally left unchanged — `sendAccessibilityEvent` is already protected by its own `try/catch (RetryableMountingLayerException)` in `SendAccessibilityEventMountItem.execute`. ## Changelog: [Android] [Fixed] - Handle missing viewState gracefully in `SurfaceMountingManager.updateState` and `updatePadding` to avoid `RetryableMountingLayerException` crashes from the Fabric batch-mount path Reviewed By: javache Differential Revision: D107768754
1 parent 861d8e0 commit cecd11e

1 file changed

Lines changed: 16 additions & 2 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,14 @@ internal constructor(
873873
return
874874
}
875875

876-
val viewState = getViewState(reactTag)
876+
val viewState = getNullableViewState(reactTag)
877+
if (viewState == null) {
878+
ReactSoftExceptionLogger.logSoftException(
879+
ReactSoftExceptionLogger.Categories.SURFACE_MOUNTING_MANAGER_MISSING_VIEWSTATE,
880+
ReactNoCrashSoftException("Unable to find viewState for tag $reactTag for updatePadding"),
881+
)
882+
return
883+
}
877884
// Do not layout Root Views
878885
if (viewState.isRoot) {
879886
return
@@ -934,7 +941,14 @@ internal constructor(
934941
return
935942
}
936943

937-
val viewState = getViewState(reactTag)
944+
val viewState = getNullableViewState(reactTag)
945+
if (viewState == null) {
946+
ReactSoftExceptionLogger.logSoftException(
947+
ReactSoftExceptionLogger.Categories.SURFACE_MOUNTING_MANAGER_MISSING_VIEWSTATE,
948+
ReactNoCrashSoftException("Unable to find viewState for tag $reactTag for updateState"),
949+
)
950+
return
951+
}
938952

939953
val prevStateWrapper = viewState.stateWrapper
940954
viewState.stateWrapper = stateWrapper

0 commit comments

Comments
 (0)