Skip to content

Remove tag from allocatedViewRegistry in destroyUnmountedShadowNode (#56274)#56274

Closed
javache wants to merge 1 commit into
facebook:mainfrom
javache:export-D98729251
Closed

Remove tag from allocatedViewRegistry in destroyUnmountedShadowNode (#56274)#56274
javache wants to merge 1 commit into
facebook:mainfrom
javache:export-D98729251

Conversation

@javache
Copy link
Copy Markdown
Member

@javache javache commented Mar 30, 2026

Summary:

When a ShadowNode is destroyed (e.g. from a superseded concurrent render
or React Transition), destroyUnmountedShadowNode calls Java
destroyUnmountedView which deletes the view from tagToViewState. However,
the C++ allocatedViewRegistry was not updated, leaving a stale entry.

This causes a crash when a subsequent executeMount encounters a Create
mutation for the same tag: allocatedViewTags.contains(tag) returns true
(stale entry from preallocate), so the Create mount item is skipped.
But the Java view was already destroyed. When subsequent mount items
(Insert, UpdateState, etc.) try to reference the tag, getViewState()
throws RetryableMountingLayerException because the tag is not in
tagToViewState.

The fix mirrors what the normal Delete mutation path already does
(line 638: allocatedViewTags.erase(tag)) - ensuring allocatedViewRegistry
stays in sync with the Java-side tagToViewState.

Changelog: [Android][Fixed] - Fix crash from stale preallocated view registry after concurrent render cancellation

Differential Revision: D98729251

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 30, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented Mar 30, 2026

@javache has exported this pull request. If you are a Meta employee, you can view the originating Diff in D98729251.

@meta-codesync meta-codesync Bot changed the title Remove tag from allocatedViewRegistry in destroyUnmountedShadowNode Remove tag from allocatedViewRegistry in destroyUnmountedShadowNode (#56274) Mar 30, 2026
javache added a commit to javache/react-native that referenced this pull request Mar 30, 2026
…acebook#56274)

Summary:

When a ShadowNode is destroyed (e.g. from a superseded concurrent render
or React Transition), destroyUnmountedShadowNode calls Java
destroyUnmountedView which deletes the view from tagToViewState. However,
the C++ allocatedViewRegistry was not updated, leaving a stale entry.

This causes a crash when a subsequent executeMount encounters a Create
mutation for the same tag: allocatedViewTags.contains(tag) returns true
(stale entry from preallocate), so the Create mount item is skipped.
But the Java view was already destroyed. When subsequent mount items
(Insert, UpdateState, etc.) try to reference the tag, getViewState()
throws RetryableMountingLayerException because the tag is not in
tagToViewState.

The fix mirrors what the normal Delete mutation path already does
(line 638: allocatedViewTags.erase(tag)) - ensuring allocatedViewRegistry
stays in sync with the Java-side tagToViewState.

Changelog: [Android][Fixed] - Fix crash from stale preallocated view registry after concurrent render cancellation

Differential Revision: D98729251
javache added a commit to javache/react-native that referenced this pull request Mar 30, 2026
…acebook#56274)

Summary:

When a ShadowNode is destroyed (e.g. from a superseded concurrent render
or React Transition), destroyUnmountedShadowNode calls Java
destroyUnmountedView which deletes the view from tagToViewState. However,
the C++ allocatedViewRegistry was not updated, leaving a stale entry.

This causes a crash when a subsequent executeMount encounters a Create
mutation for the same tag: allocatedViewTags.contains(tag) returns true
(stale entry from preallocate), so the Create mount item is skipped.
But the Java view was already destroyed. When subsequent mount items
(Insert, UpdateState, etc.) try to reference the tag, getViewState()
throws RetryableMountingLayerException because the tag is not in
tagToViewState.

The fix mirrors what the normal Delete mutation path already does
(line 638: allocatedViewTags.erase(tag)) - ensuring allocatedViewRegistry
stays in sync with the Java-side tagToViewState.

Changelog: [Android][Fixed] - Fix crash from stale preallocated view registry after concurrent render cancellation

Differential Revision: D98729251
…acebook#56274)

Summary:
Pull Request resolved: facebook#56274

When a ShadowNode is destroyed (e.g. from a superseded concurrent render
or React Transition), destroyUnmountedShadowNode calls Java
destroyUnmountedView which deletes the view from tagToViewState. However,
the C++ allocatedViewRegistry was not updated, leaving a stale entry.

This causes a crash when a subsequent executeMount encounters a Create
mutation for the same tag: allocatedViewTags.contains(tag) returns true
(stale entry from preallocate), so the Create mount item is skipped.
But the Java view was already destroyed. When subsequent mount items
(Insert, UpdateState, etc.) try to reference the tag, getViewState()
throws RetryableMountingLayerException because the tag is not in
tagToViewState.

The fix mirrors what the normal Delete mutation path already does
(line 638: allocatedViewTags.erase(tag)) - ensuring allocatedViewRegistry
stays in sync with the Java-side tagToViewState.

Changelog: [Android][Fixed] - Fix crash from stale preallocated view registry after concurrent render cancellation

Differential Revision: D98729251
@meta-codesync meta-codesync Bot closed this in 97cf220 Mar 31, 2026
@facebook-github-tools facebook-github-tools Bot added the Merged This PR has been merged. label Mar 31, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented Mar 31, 2026

This pull request has been merged in 97cf220.

@react-native-bot
Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @javache in 97cf220

When will my fix make it into a release? | How to file a pick request?

@javache javache deleted the export-D98729251 branch April 8, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged This PR has been merged. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants