From bfe91b0d4f265dee7e113d560defb4bb4fb20e0e Mon Sep 17 00:00:00 2001 From: Eric Kreutzer Date: Sun, 22 Mar 2026 16:06:32 -0600 Subject: [PATCH 1/2] Fix Android a11y descendant race in ReactViewGroup --- .../facebook/react/views/view/ReactViewGroup.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt index 44aeba9e2047..2910c1308ba6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt @@ -997,12 +997,12 @@ public open class ReactViewGroup public constructor(context: Context?) : } else if (axOrderParentOrderList != null) { // view is a container so add its children normally if (!isFocusable) { - super.addChildrenForAccessibility(outChildren) + safeAddChildrenForAccessibility(outChildren) return // If this view can coopt, turn the focusability off its children but add them to the tree } else if (isFocusable && (contentDescription == null || contentDescription == "")) { - super.addChildrenForAccessibility(outChildren) + safeAddChildrenForAccessibility(outChildren) for (i in 0..) { + try { super.addChildrenForAccessibility(outChildren) + } catch (error: IllegalArgumentException) { + // Android 16 can race while building accessibility child lists during fast re-parenting. + if (error.message?.contains("descendant of this view") != true) { + throw error + } } } From 94483a48a66e2db9ed37364623d3c15a9a201667 Mon Sep 17 00:00:00 2001 From: Eric Kreutzer Date: Mon, 23 Mar 2026 15:05:23 -0600 Subject: [PATCH 2/2] Log soft exception for RVG accessibility descendant race --- .../com/facebook/react/bridge/ReactSoftExceptionLogger.kt | 4 ++++ .../java/com/facebook/react/views/view/ReactViewGroup.kt | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactSoftExceptionLogger.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactSoftExceptionLogger.kt index 51ff4d0224b1..877f2fc2843e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactSoftExceptionLogger.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactSoftExceptionLogger.kt @@ -11,6 +11,7 @@ import androidx.annotation.StringDef import com.facebook.common.logging.FLog import com.facebook.proguard.annotations.DoNotStrip import com.facebook.react.bridge.ReactSoftExceptionLogger.Categories.CLIPPING_PROHIBITED_VIEW +import com.facebook.react.bridge.ReactSoftExceptionLogger.Categories.RVG_ADD_CHILDREN_FOR_ACCESSIBILITY import com.facebook.react.bridge.ReactSoftExceptionLogger.Categories.RVG_IS_VIEW_CLIPPED import com.facebook.react.bridge.ReactSoftExceptionLogger.Categories.RVG_ON_VIEW_REMOVED import com.facebook.react.bridge.ReactSoftExceptionLogger.Categories.SOFT_ASSERTIONS @@ -21,6 +22,7 @@ import java.util.concurrent.CopyOnWriteArrayList internal object ReactSoftExceptionLogger { @Retention(AnnotationRetention.SOURCE) @StringDef( + RVG_ADD_CHILDREN_FOR_ACCESSIBILITY, RVG_IS_VIEW_CLIPPED, RVG_ON_VIEW_REMOVED, CLIPPING_PROHIBITED_VIEW, @@ -31,6 +33,8 @@ internal object ReactSoftExceptionLogger { /** Constants that listeners can utilize for custom category-based behavior. */ object Categories { + const val RVG_ADD_CHILDREN_FOR_ACCESSIBILITY: String = + "ReactViewGroup.addChildrenForAccessibility" const val RVG_IS_VIEW_CLIPPED: String = "ReactViewGroup.isViewClipped" const val RVG_ON_VIEW_REMOVED: String = "ReactViewGroup.onViewRemoved" const val CLIPPING_PROHIBITED_VIEW: String = "ReactClippingProhibitedView" diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt index 2910c1308ba6..880c15362a4b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt @@ -1021,7 +1021,12 @@ public open class ReactViewGroup public constructor(context: Context?) : super.addChildrenForAccessibility(outChildren) } catch (error: IllegalArgumentException) { // Android 16 can race while building accessibility child lists during fast re-parenting. - if (error.message?.contains("descendant of this view") != true) { + if (error.message?.contains("descendant of this view") == true) { + logSoftException( + ReactSoftExceptionLogger.Categories.RVG_ADD_CHILDREN_FOR_ACCESSIBILITY, + error, + ) + } else { throw error } }