Skip to content

[Due for payment 2026-10-15] [$175] [Sentry: APP-K0G] Fabric addViewAt crashes adding view into non-ViewGroup #102741

Open

Description

@mountiny

Sentry

https://expensify.sentry.io/issues/APP-K0G

Impact (snapshot at filing)

  • Users (total since first seen): 91
  • Events: 91
  • Users (last 14d): not pulled separately
  • First seen: 2026-08-10
  • Last seen: now (ongoing)
  • Platform: Android (HybridApp)
  • App version(s): 9.4.9x through 9.5.0 pre-release builds
  • Affected route(s) (parameterized): n/a — native Fabric mounting, not a JS route
  • Mechanism: UncaughtExceptionHandler (fatal)

Stack trace (top frames, first-party only)

com.facebook.react.fabric.mounting.SurfaceMountingManager.addViewAt (SurfaceMountingManager.kt:330)
com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem.execute
com.facebook.react.fabric.mounting.MountItemDispatcher.executeOrEnqueue
com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchMountItems
com.facebook.react.fabric.FabricUIManager$DispatchUIFrameCallback.doFrameGuarded

Error: IllegalStateException: Unable to add a view into a view that is not a ViewGroup

Suspected cause

Fabric's mounting manager tries to add a view into a parent that has already been removed or replaced, likely a race between an unmount and a queued mount item during a fast re-render.

Reproduction

Unknown — see Sentry events linked from the Sentry issue.

Related

  • Sibling Sentry IDs: none identified
  • Prior GH issues: none found
Upwork Automation - Do Not Edit
Issue OwnerCurrent Issue Owner: @mallenexpensify

Activity

  1. self-assigned this
    on Oct 1, 2026
  2. added
    ExternalAdded to denote the issue can be worked on by a contributor
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 1, 2026
  3. melvin-bot commented on Oct 1, 2026

    @melvin-bot

    Triggered auto assignment to Contributor-plus team member for initial proposal review - @eVoloshchak (External)

  4. changed the title [-][Sentry: APP-K0G] Fabric addViewAt crashes adding view into non-ViewGroup[/-] [+][$175] [Sentry: APP-K0G] Fabric addViewAt crashes adding view into non-ViewGroup[/+] on Oct 1, 2026
  5. melvin-bot commented on Oct 1, 2026

    @melvin-bot
  6. MelvinBot commented on Oct 1, 2026

    @MelvinBot
    Contributor

    Proposal

    What is the root cause of that problem?

    Android Fabric crashes in addViewAt when the parent tag has a view state but no usable ViewGroup view. See SurfaceMountingManager.kt:312-331. The check view !is ViewGroup also fails when view is null.

    The most likely source is a placeholder view state. updateEventEmitter creates an empty ViewState for any tag that Java no longer has (SurfaceMountingManager.kt:959). When the next batch inserts into that tag, it crashes. Java loses a tag when mount items run in a different order than the shadow tree expects.

    This belongs to the same family as [$250] [Sentry: APP-7AR / APP-H7A] HybridApp Android Fabric mount crash — addViewAt/removeViewAt on clipping views. In RN 0.86, several of those paths only log a soft exception. A broken batch now survives one step longer and fails here. This fits the first-seen date: 2026-08-10 is the day upgrade react native to 0.86.0 merged.

    Fix Android Fabric mount crashes from merged mounting transactions (APP-7AR / APP-H7A) shipped in 9.4.93-3. It removed the main source: merged transactions that mounted out of order. Other sources remain:

    • A delete is delayed during an active touch, and the same tag is recreated before the touch ends.
    • Differ bugs in flatten and unflatten. Upstream fixed these after 0.86.0 in 361bc24.
    • Reanimated layout animations rewrite transactions.

    Upstream already made the matching removeViewAt case a soft exception in 3f553d7. The addViewAt case still crashes.

    What changes do you think we should make in order to solve the problem?

    1. Check Sentry APP-K0G for events on 9.4.93-3 or later. If there are none, close this issue as fixed by PR Fix Android Fabric mount crashes from merged mounting transactions (APP-7AR / APP-H7A) #101057.
    2. If events continue, add an App patch to RN SurfaceMountingManager.addViewAt. When the parent has no ViewGroup view, the patch should log a ReactNoCrashSoftException and skip the insert instead of crashing. This mirrors upstream's removeViewAt change. Put the parent's view class in the message so Sentry shows which component is involved.
    3. In a separate patch, backport upstream differ fix 361bc24 if it applies cleanly to 0.86.0.

    Step 2 can leave a single view missing until the next render. That is better than a fatal crash, and it is the same trade-off upstream accepted for removeViewAt.

    What alternative solutions did you explore? (Optional)

    • JS-side fix: I found no App component that passes children to a native view that is not a ViewGroup, such as Image, TextInput, Lottie, or Switch. A JS-side cause would also crash the same user every time. That does not fit 91 events from 91 users.
    • View recycling or preallocation: I ruled these out. enableViewRecycling is off by default, and preallocation is queued before any batch can run.
    • Disable mount-item reordering globally: Patch +015 already does this for merged batches. Upstream reports say it does not fix the differ cases.
    Investigation details

    Confidence: medium. I couldn't connect to Sentry during this run. So I couldn't check two things:

    • Whether events continue on 9.4.93-3 or later. The issue lists "9.4.9x through 9.5.0", which suggests they might.
    • Which view class the parent tag belongs to.

    How the crash happens:

    What App patch +015 covers: react-native+0.86.0+015+fix-merged-transaction-mount-order.patch mounts merged batches in differ order. The earlier +015 patch could leave several pending transactions for one surface, which was a second source of out-of-order mounts. The new patch fixes that too. It does not cover unmerged transactions, delayed deletes during touches, differ bugs, or transactions rewritten by Reanimated.

    Ruled out: A real non-ViewGroup parent is unlikely:

    • Text nodes are flattened on Android, so they never act as parents.
    • RN Image throws in JS if it is given children.
    • No App code passes children to TextInput, Lottie, or Switch.
    • No library changed its view from ViewGroup to non-ViewGroup in the 0.86 or Expo 57 upgrade.

    Sentry data that would settle this:

    • Version split before and after 9.4.93-3.
    • Breadcrumbs just before the crash, such as Unable to find viewState for tag.
    • The screen where it happened. One lead is chat scrolling: the maintainVisibleContentPosition toggle in useReportActionsScroll.ts:207-216 flattens and unflattens many views in one commit.

    Related issues


    Next Steps for Contributor+ team:
    To accept: @MelvinBot implement [this](https://github.com/Expensify/App/issues/102741) to create a draft PR.
    To refine: @MelvinBot <your feedback>
    To reject: Explain why you are rejecting Melvin's proposal.


    view run

  7. mountiny commented on Oct 1, 2026

    @mountiny
    ContributorAuthor

    @eVoloshchak can you review the proposal from melvin please?

  8. eVoloshchak commented on Oct 2, 2026

    @eVoloshchak
    Contributor

    Check Sentry APP-K0G for events on 9.4.93-3 or later.

    Image

    This is present in release 9.4.94-0 , so it wasn't resolved by #101057

    @MelvinBot, implement this

  9. MelvinBot commented on Oct 2, 2026

    @MelvinBot
    Contributor

    🤖 Draft PR created: Soft-fail Fabric addViewAt into a non-ViewGroup parent and backport upstream differ fix (APP-K0G)
    Please mark it as "Ready for review" when it is ready for review.

    It adds the two patches from steps 2 and 3 of the proposal:

    • +045: when the parent is not a ViewGroup, addViewAt now logs a ReactNoCrashSoftException with the parent view class and skips the insert, instead of crashing. This matches upstream's removeViewAt change.
    • +046: backports upstream differ fix 361bc24. It needed one change: 0.86.0's DiffMap has no contains, so the patch uses find(...) != end().

    Before you merge, note:

    • I couldn't run native builds here. CI's Android and iOS builds are the compile check. +046 is C++ code shared by both platforms.
    • App doesn't forward soft exceptions to Sentry, so the new log goes to logcat only. To confirm the fix, check whether APP-K0G events stop on the release that includes this PR.
  10. mountiny commented on Oct 5, 2026

    @mountiny
    ContributorAuthor

    @eVoloshchak how is this looking?

  11. 6 remaining items

  12. changed the title [-][$175] [Sentry: APP-K0G] Fabric addViewAt crashes adding view into non-ViewGroup[/-] [+][Due for payment 2026-10-15] [$175] [Sentry: APP-K0G] Fabric addViewAt crashes adding view into non-ViewGroup[/+] on Oct 8, 2026
  13. melvin-bot commented on Oct 8, 2026

    @melvin-bot

    @eVoloshchak

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.5-2 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-10-15. 🎊

    The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]. If no checklist is needed for this issue, you can click: [no checklist button]

  14. mountiny commented on Oct 12, 2026

    @mountiny
    ContributorAuthor

    Monitoring

  15. added and removed on Oct 12, 2026
  16. added
    Awaiting PaymentAuto-added when associated PR is deployed to production
    and removed on Oct 14, 2026
  17. melvin-bot commented on Oct 14, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

  18. melvin-bot commented on Oct 14, 2026

    @melvin-bot

    Payment Summary

    Resolving PRs:

    BugZero Checklist (@mallenexpensify)

    • I have confirmed assignees, roles, and Upwork contracts look correct
    • I have paid out Upwork contracts / manual NewDot requests
    • [BugZero Assignee] I have created a GH issue for creating/updating the regression test once above steps have been agreed upon
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributor

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions