Repository navigation
[$175] [Sentry: APP-7AR] HybridApp Android: Fabric addViewAt "failed to insert view" still crashes after #101057 #104743
Copy link
Copy link
Open
Labels
BugSomething is broken. Auto assigns a BugZero manager.Something is broken. Auto assigns a BugZero manager.DailyKSv2KSv2ExternalAdded to denote the issue can be worked on by a contributorAdded to denote the issue can be worked on by a contributor
Description
Sentry
https://expensify.sentry.io/issues/APP-7AR
Impact (snapshot at filing)
- Users (total since first seen): 1,395
- Events: 1,501
- Users (last 14d, all versions): 254
- Users (last 14d, production 9.5.13 to 9.5.16 builds): about 51. 9.5.13-0: 28, 9.5.15-1: 16, 9.5.14-0: 5, 9.5.16-0: 2
- First seen: 2026-03-11
- Last seen: 2026-10-22 (ongoing)
- Platform: HybridApp Android
- App version(s): every Android build from 9.5.5 to 9.5.16. The crash continues after the fix in Fix Android Fabric mount crashes from merged mounting transactions (APP-7AR / APP-H7A) #101057 shipped.
- Affected screen:
TabNavigator - Mechanism: chained, level fatal
Stack trace (top frames)
IllegalStateException: addViewAt: failed to insert view [N] into parent [M] at index 1
at com.facebook.react.fabric.mounting.SurfaceMountingManager.addViewAt(SurfaceMountingManager.kt:393)
Caused by: IndexOutOfBoundsException: index=1 count=0
at android.view.ViewGroup.addInArray(ViewGroup.java:5639)
at android.view.ViewGroup.addViewInner(ViewGroup.java:5526)
at android.view.ViewGroup.addView(ViewGroup.java:5323)
at com.facebook.react.views.view.ReactClippingViewManager.addView(ReactClippingViewManager.kt:36)
at com.facebook.react.fabric.mounting.SurfaceMountingManager.addViewAt(SurfaceMountingManager.kt:385)
at com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem.execute(IntBufferBatchMountItem.kt:122)
at com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchMountItems(MountItemDispatcher.kt:250)
Suspected cause
Fabric tells a clipping view (removeClippedSubviews) to insert a child at index 1 while the native parent has no children. The patch from #101057 (react-native+0.86.0+015+fix-merged-transaction-mount-order.patch) fixed the mount order for merged transactions, but another path still sends a mount instruction with an index that the clipping view does not have.
Reproduction
Unknown. See the Sentry events linked from the Sentry issue.
Related
- Prior GH issues: [Due for payment 2026-10-02] [$250] [Sentry: APP-7AR / APP-H7A] HybridApp Android Fabric mount crash — addViewAt/removeViewAt on clipping views #98791 (closed 2026-10-13)
- Prior fix: Fix Android Fabric mount crashes from merged mounting transactions (APP-7AR / APP-H7A) #101057 (merged 2026-09-23)
- Sibling Sentry IDs: APP-H7A (
removeViewAt, also covered by [Due for payment 2026-10-02] [$250] [Sentry: APP-7AR / APP-H7A] HybridApp Android Fabric mount crash — addViewAt/removeViewAt on clipping views #98791)
Upwork Automation - Do Not Edit
- Upwork Job URL: https://www.upwork.com/jobs/~022113270930182289158
- Upwork Job ID: 2113270930182289158
- Last Price Increase: 2026-10-22
Issue Owner
Current Issue Owner: @sobitneupaneReactions are currently unavailable
Metadata
Metadata
Assignees
Labels
BugSomething is broken. Auto assigns a BugZero manager.Something is broken. Auto assigns a BugZero manager.DailyKSv2KSv2ExternalAdded to denote the issue can be worked on by a contributorAdded to denote the issue can be worked on by a contributor
Type
Projects
- StatusShow more project fieldsNo status
Activity
melvin-bot commentedon Oct 22, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @sobitneupane (
External)[-][Sentry: APP-7AR] HybridApp Android: Fabric addViewAt "failed to insert view" still crashes after #101057[/-][+][$175] [Sentry: APP-7AR] HybridApp Android: Fabric addViewAt "failed to insert view" still crashes after #101057[/+]melvin-bot commentedon Oct 22, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022113270930182289158
MelvinBot commentedon Oct 22, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
HybridApp Android crashes when Fabric inserts a view at index 1 into a native parent that has no children.
What is the root cause of that problem?
The native view tree falls out of sync with Fabric's shadow tree. The parent's first child either never gets added, or something removes it without telling Fabric. When the next insert arrives at index 1,
ViewGroup.addViewthrowsIndexOutOfBoundsExceptionandSurfaceMountingManager.addViewAtrethrows it as a fatal error.Two corrections to the issue description:
ReactClippingViewManager.kt:36is the plainparent.addViewbranch, which runs only whenremoveClippedSubviewsis off (ReactClippingViewManager.kt:29-37). Any plainViewcan be the parent.TabNavigatoris probably incidental. That route name was added on 2026-04-24, but the crash was first seen on 2026-03-11. Most narrow-layout screens now sit under it, so most events report it.The line numbers in the stack (385/393) show that the crashing builds already include
+015,+016, and+045. Earlier patches each closed one source of the desync (+015merged-transaction order,+046differ flatten bug). Other sources still reach this path, for example a skipped insert when the child'sViewStateis missing, or a child detached through the "View already has a parent" branch. Without Fabric mount logs from a failing session, I can't confirm which source is left.Code references
addViewAtrethrows bothIllegalStateExceptionandIndexOutOfBoundsExceptionas fatal: SurfaceMountingManager.kt:380-392+015explains the merged-transaction source and lists APP-7AR: details.md:112-116+045/+046/+047handle the related mount crashes (APP-K0G, APP-H7A): details.md:370-388+045and+047turned the sibling crashes into soft exceptions.What changes do you think we should make in order to solve the problem?
Add a new React Native patch,
react-native+0.86.0+048+soft-fail-addViewAt-index-out-of-bounds-APP-7AR.patch, toSurfaceMountingManager.addViewAt. It follows the same approach as+045and+047:IndexOutOfBoundsExceptioncatch, read the parent's child count from the view group manager. This returns the correct count for clipping parents too.ReactNoCrashSoftExceptionwith the parent tag, parent class, index, and child count.details.mdentry. Link the upstream fix and say to drop the patch once React Native ships it.This matches the open upstream fix by a Meta engineer, Fix IndexOutOfBoundsException crash in SurfaceMountingManager.addViewAt (#57172). Our version uses the manager's child count, not the raw
childCount, so it is also correct for clipping parents.Trade-offs: positions stay correct because Fabric sets each child's frame directly. Sibling draw order and accessibility order can be wrong until the parent re-renders. Later removes still work because they fall back to finding the child by tag. The soft-exception logs keep the desync visible so we can track its source.
What alternative solutions did you explore? (Optional)
Related issues
+045) is the model for this one.Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/104743)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
Abdallah-1551 commentedon Oct 22, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
HybridApp Android still crashes fatally in
SurfaceMountingManager.addViewAt("failed to insert view [N] into parent [M] at index 1", caused byIndexOutOfBoundsException: index=1 count=0). It happens on builds that already include the earlier mount-order patches (+015and related). The crash affects about 50 production users per 14 days. We need to stop the fatal crash and keep enough diagnostics to find the remaining desync source.What is the root cause of that problem?
INSERT(parent, child, index=1), but the native parent has 0 children. Child 0 was never attached or was detached outside Fabric's knowledge.ViewGroup.addView(child, 1)then throwsIndexOutOfBoundsException.SurfaceMountingManager.addViewAtrethrows that exception as a fatalIllegalStateException. A mount batch (IntBufferBatchMountItem) cannot be retried or partially rolled back, so one bad index kills the app.ReactClippingViewManager.kt:36is the plainparent.addView(...)branch. It runs whenremoveClippedSubviewsis off, so the parent is not necessarily a clipping view.TabNavigatoris probably incidental, because most narrow-layout screens sit under it.ViewStateis missing, or a child detached through the "View already has a parent" branch. We cannot identify it without a repro or Fabric mount logs. The right fix now is to make this path non-fatal and observable, as+045and+047did for the sibling crashes.What changes do you think we should make in order to solve the problem?
Add a new patch,
patches/react-native/react-native+0.86.0+048+soft-fail-addViewAt-index-out-of-bounds-APP-7AR.patch, touching onlySurfaceMountingManager.kt.addViewAt, change theIndexOutOfBoundsExceptionhandler. It must use the view group manager's child count, notparentView.childCount, because clipping parents report a different count:index <= childCount, a failed retry, and non-index exceptions. Unrelated bugs still surface and are not masked.ViewState.mCurrentPropsif cheaply available.patches/react-native/details.mdin the existing format: upstream issue/PR links (RN issue [Due for payment 2025-04-16] [$250] Scan – RBR is not displayed in LHN when editing an amount to be higher than the scanned amount #57017 and the open upstream fix foraddViewAtIOOBE), the reason (APP-7AR), and "remove when React Native ships the upstream fix".Trade-offs: Fabric sets each child's layout directly, so position and size stay correct. Sibling z-order and accessibility order may be wrong until the parent re-renders. Later
removeViewAtcalls still work because they fall back to finding the child by tag. This is far better than a fatal crash.What alternative solutions did you explore? (Optional)
index > childCountbefore every insert: rejected. Some view managers under-report their child count, so a pre-check could change inserts that work today. Catching the exception only changes the path that crashes today.Testing
npm run patch/patch-packageand confirm+048applies cleanly on top of+015,+016,+045,+046, and+047. Build the HybridApp Android debug and release variants.ReactViewGroupwith 0 children and callSurfaceMountingManager.addViewAt(parentTag, childTag, 1).ReactNoCrashSoftExceptionis logged.addViewthrows for a valid index. Expected: the original fatalIllegalStateExceptionis still thrown.removeClippedSubviews=trueand confirm the manager's child count is used and the insert is recovered.camesenin commentedon Oct 22, 2026
Contributor details
Your Expensify account email: camesenin@gmail.com
Upwork Profile Link: https://www.upwork.com/freelancers/~0170d6b02e9440e604
Proposal
Please re-state the problem that we are trying to solve in this issue.
On HybridApp Android, the application crashes fatal in Fabric's mounting phase with
IllegalStateException: addViewAt: failed to insert view [tag] into parent [parentTag] at index 1, caused by an underlyingIndexOutOfBoundsException: index=1 count=0. This continues to crash users even after patch+015(PR #101057).What is the root cause of that problem?
In React Native Fabric architecture on Android (
SurfaceMountingManager.kt:380-392), when mounting view mutations computed by the shadow tree:viewGroupManager.addView(parentView, view, index), if the native view tree is out of sync with Fabric's shadow tree (e.g. index 1 is requested but the parent currently has count 0 because an earlier child was dropped, delayed, or removed by a layout pass), Android'sViewGroup.addViewthrowsIndexOutOfBoundsException.SurfaceMountingManager.kt:SurfaceMountingManager.addViewAtcatchesIndexOutOfBoundsExceptionand unconditionally re-throws it as a fatalIllegalStateException, causing an immediate app crash for the user.+015resolved transaction-mount ordering and patch+046resolved nested flatten bugs, subtle race conditions in Android's native view hierarchy still trigger out-of-bounds indices.APP-K0Gin patch+045andAPP-H7Ain patch+047): rather than terminating the application fatally for recoverable layout hierarchy discrepancies, the engine should log aReactNoCrashSoftExceptionand safely append the view at the currentmanagerChildCount.What changes do you think we should make in order to solve the problem?
Introduce patch
react-native+0.86.0+048+soft-fail-addViewAt-index-out-of-bounds-APP-7AR.patchmodifyingSurfaceMountingManager.kt:When
IndexOutOfBoundsExceptionoccurs andindex > managerChildCount:viewGroupManager.getChildCount(parentView)(which correctly accounts for clipping managers likeReactClippingViewManageras well as standardReactViewGroup).ReactNoCrashSoftExceptionviaReactSoftExceptionLoggercontainingparentTag,parentViewclass name, requestedindex, actualchildCount, and childtag.managerChildCountinstead of throwing a fatal exception.Add an entry to
patches/react-native/details.mddocumenting:APP-7AR.Why this solution is optimal:
+045and+047inpatches/react-native/details.md.viewGroupManager.getChildCount(parentView)guarantees accuracy across all view manager types.What alternative solutions did you explore? (Optional)
Rejected. Skipping the child leaves UI elements unmounted and missing from the screen. Appending at
managerChildCountmounts the view while Fabric's explicit layout properties position and size it correctly.index > childCountbefore everyaddView:Rejected. Some custom view managers dynamically manage their child list; adding an eager pre-check could disrupt valid mounts. Catching the specific exception guarantees that only currently-crashing paths are altered.
Testing
npm run patchto ensure patch applies cleanly over+015,+045,+046, and+047.melvin-bot commentedon Oct 22, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
xian96xx commentedon Oct 25, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
On HybridApp Android (React Native 0.86 / Fabric), Sentry issue
APP-7AR(java.lang.IllegalStateException: Failed to execute: ... SurfaceMountingManager.addViewAt) continues to crash in production (v9.3.39-2/v9.4.1-2) even after PR #101057 addedreact-native+0.86.0+045+soft-fail-addViewAt-non-ViewGroup-parent-APP-K0G.patchto soft-fail whenparentView.viewis not aViewGroup.When
parentView.viewis a validViewGroup(ReactViewGroup),SurfaceMountingManager.addViewAtstill throws a fatalIndexOutOfBoundsExceptioninsidegetViewGroupManager(parentViewState).addView(parentView, view, index)(for exampleindex=1 count=0orindex=2 count=1), whichIntBufferBatchMountItem.executewraps in an uncaughtIllegalStateException.What is the root cause of that problem?
In
packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.kt(around lines 318–408),addViewAt(parentTag, tag, index)computes the target index from C++ShadowTreediffing (IntBufferBatchMountItem), whereindexassumesparentView's current Android child count matches the shadow tree's precedent sibling count.However, in
SurfaceMountingManager.kton RN 0.86 (combined with our existing soft-fail patches015,016,045, and047), there are three concrete paths where the actual child count managed bygetViewGroupManager(parentViewState)is smaller thanindexat the momentgetViewGroupManager(parentViewState).addView(parentView, view, index)runs:addViewAtitself (SurfaceMountingManager.kt:350-378):When
view.parent != null, patch015soft-logs aReactNoCrashSoftExceptionand lines 374–377 detachviewfrom its existingviewParentviaviewParent.endViewTransition(view)andviewParent.removeView(view). WhenviewParent === parentView(i.e.viewwas already attached toparentViewat an earlier index such as0whenparentViewhad1child, and a merged/reordered mount item re-inserts it atindex = 1),viewParent.removeView(view)decrementsparentView's child count from1to0immediately before line 381 callsaddView(parentView, view, 1)—deterministically throwingIndexOutOfBoundsException: index=1 count=0.Insertskipped in the sameIntBufferBatchMountItem(SurfaceMountingManager.kt:333-340, plus patch045):If child
0'sViewStatewas already deleted (getNullableViewState(tag) == nullat line 333) or skipped by a soft-fail guard,addViewAt(parentTag, child0Tag, 0)returns early without adding a child toparentView. The very next instruction in the sameIntBufferBatchMountItem(addViewAt(parentTag, child1Tag, 1)) still carriesindex = 1from the shadow diff whileparentViewhas0children, throwingIndexOutOfBoundsException: index=1 count=0.removeViewAt(SurfaceMountingManager.kt:469-482):removeViewAtalready tolerates index mismatches and already-removed children by logging aReactNoCrashSoftExceptionand clamping/decrementing backward instead of crashing, whereasaddViewAtpasses the unvalidatedindexstraight intogetViewGroupManager(parentViewState).addView(parentView, view, index)and rethrows any exception insidecatch (e: IllegalStateException)/ uncaughtIndexOutOfBoundsException.What changes do you think we should make in order to solve the problem?
We should add a new React Native patch
patches/react-native/react-native+0.86.0+048+soft-fail-addViewAt-index-out-of-bounds-APP-7AR.patch(and document it inpatches/react-native/details.md) that updatesSurfaceMountingManager.addViewAtinpackages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.kt:getViewGroupManager(parentViewState).getChildCount(parentView)(notparentView.childCountdirectly):In
SurfaceMountingManager.kt, child insertion and lookup are delegated throughIViewGroupManager(getViewGroupManager(parentViewState).addView(parentView, view, index)at line 381,viewGroupManager.getChildAt(...)at line 456,viewGroupManager.getChildCount(parentView)at line 521) because customIViewGroupManagerimplementations may wrap or virtualize children such thatviewGroupManager.getChildCount(parentView)differs from rawparentView.childCount.indexafter anyviewParent.removeView(view)detach and logReactNoCrashSoftException(TAG, ...):Right before calling
viewGroupManager.addView(parentView, view, safeIndex)(after theif (viewParent != null)block at lines 351–378 has already detachedviewif needed), checkval childCount = viewGroupManager.getChildCount(parentView). Ifindex < 0 || index > childCount, log aReactNoCrashSoftExceptionviaReactSoftExceptionLogger.logSoftException(TAG, ...)(using the class's existingTAGconstant) with diagnostic context (tag,parentTag, requestedindex, actualchildCount), and clampval safeIndex = index.coerceIn(0, childCount).IndexOutOfBoundsExceptionas defense-in-depth:As noted in
SurfaceMountingManager.kt:506-520, some customViewManagerimplementations overridegetChildCountinconsistently with their internaladdView. IfviewGroupManager.addView(parentView, view, safeIndex)still throwsIndexOutOfBoundsException, catch it and log aReactNoCrashSoftExceptionwithTAGinstead of crashing the app.What alternative solutions did you explore? (Optional)
parentView.childCountdirectly:SurfaceMountingManagerinserts throughgetViewGroupManager(parentViewState).addView(parentView, view, index), notparentView.addView(view, index). UsingviewGroupManager.getChildCount(parentView)matchesremoveViewAt(SurfaceMountingManager.kt:521) and respects customIViewGroupManagerimplementations, while thecatch (e: IndexOutOfBoundsException)block guards against custom managers whosegetChildCountandaddViewdiverge.[0, childCount]: Dropping the view entirely leaves the mounted view subtree blank even when the childViewStateis valid; clamping tochildCountappends the view in its parentViewGroupso it remains visible and interactive while reporting the non-fatal invariant violation to Sentry/soft-exception logs.melvin-bot commentedon Oct 25, 2026
📣 @xian96xx! 📣
Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
Please follow these steps:
Format:
sobitneupane commentedon Oct 26, 2026
@mountiny I could not prioritize this issue. Could you please reassign it?
shilo1979jk commentedon Oct 26, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
HybridApp Android still terminates with
SurfaceMountingManager.addViewAt: failed to insert viewafter #101057. The supplied cause isIndexOutOfBoundsException: index=1 count=0: Fabric requests an insertion beyond the native parent's current children. We need bounded recovery for this invalid insertion while preserving diagnostics and avoiding duplicate or silently missing views.What is the root cause of that problem?
The proven failure is a disagreement between a Fabric insertion index and the native child list, followed by an unconditional fatal rethrow. In React Native 0.86.0's SurfaceMountingManager,
addViewAtdelegates to the view manager and wrapsIndexOutOfBoundsExceptioninIllegalStateException. Nothing repairs this index mismatch before it escapes the mount batch.Two details matter:
ReactClippingViewManager.kt:36is the non-clippingparent.addView(child, index)branch in the versioned source. This stack does not prove thatremoveClippedSubviewscaused the crash.+015patch fixes mutation ordering for merged transactions. The provided+045patch soft-fails a parent that is not aViewGroup. A validViewGroupwith an invalid insertion index passes that guard, so+045cannot handle this crash. These are different paths, as documented in Expensify's patch inventory.There are concrete ways to reach the remaining mismatch: an earlier insertion can return because its child
ViewStateis absent; the existing-parent recovery can detach a child before reinsertion, reducing the target count when both parents are the same. Both are testable fault scenarios. Neither is established as the production trigger by this stack.TabNavigatoridentifies the active route, not necessarily the component that caused the mismatch. Without the preceding mount operations, the originating desynchronization remains unknown.What changes do you think we should make in order to solve the problem?
Add the next available ordered React Native patch for
APP-7AR, documented inpatches/react-native/details.md. Change only the out-of-bounds recovery path inaddViewAt, building on upstream PR #57172, which is still open at review time, with these safeguards:Attempt the requested insertion first. Keep valid inserts and existing
IllegalStateExceptionhandling unchanged. Do not pre-clamp every index: RN explicitly warns that custom managers can report counts that differ from their actual insertion behavior.In the
IndexOutOfBoundsExceptioncatch, obtain the sameviewGroupManagerused for insertion and readgetChildCount(parentView)after any existing-parent detachment. A clipping manager counts logical children, including clipped ones; rawparentView.childCountcan be smaller and choose the wrong position.Recover only when the requested index is nonnegative and greater than a nonnegative manager count. Before retrying, require that the failed insert left the child detached and absent from the manager's logical child list. A custom manager may throw after partially attaching/registering a child; blindly retrying could duplicate it. If the child is already present or state cannot be established safely, preserve the contextual failure rather than silently drop an insertion. If the count/child inspection itself throws, retain that diagnostic alongside the original exception and do not attempt another insertion. Negative indices and failures at otherwise valid indices are outside this recovery.
Retry once, appending at that manager count. On success, log a
ReactNoCrashSoftExceptionwith a stableAPP-7ARrecovery prefix and context: surface ID, parent/child tags and classes, requested index, manager/raw counts and the child's original parent before detachment. Retain the original exception as the cause. These details distinguish missing siblings from same-parent reinsertion without collecting user content.If the append fails, throw a contextual exception whose cause is the retry failure, retaining the first insertion failure as suppressed context. Do not catch every runtime error and report only the original exception: that loses why recovery failed. Do not continue the batch as if a child was inserted when both attempts failed.
This is a narrowly scoped crash mitigation, not proof that Fabric's original tree divergence is fixed. Appending keeps the valid child mounted in the recoverable case, but sibling drawing/accessibility order may differ; layout, visibility and subsequent mount operations must be verified rather than assumed correct. Follow both recovered and residual fatal events after rollout to locate the upstream cause.
Validation: apply the patch on top of the actual installed
0.86.0patch sequence and build HybridApp Android. Extend the upstreamSurfaceMountingManagerTestapproach with an empty parent/index 1, a nonempty parent/oversized index, same-parent detach/reinsert and a missing preceding child. Assert the child is present exactly once, a soft exception is emitted, and subsequent insert/remove operations target the right tags. Cover clipping with logical versus attached counts, a valid insert despite an under-reporting manager, partial-mutation failure, negative index, valid-index failure and a failed fallback retaining both exceptions. Exercise tabs, RHP navigation, workspace changes and transaction merging.What alternative solutions did you explore? (Optional)
TabNavigator, or repeat+015/+045: the supplied stack does not justify those changes. Fixing a newly identified differ/mount-order cause would be preferable once the preceding operations establish one.