-
Notifications
You must be signed in to change notification settings - Fork 25.2k
Fix "Cannot read property 'canonical' of undefined" in Fabric getListener when event target is not a live fiber - #58418
Open
heecheolman wants to merge 1 commit into
Open
Conversation
...defined getListener guards the fiber's stateNode with a strict null check: inst = inst.stateNode; if (null === inst) return null; Within the reconciler this is sufficient (stateNode is initialized to null and reset to null on detach), but the responder event path receives its target from native dispatch. When the instance handle delivered across the JSI boundary is no longer a live host fiber (e.g. a touch delivered after the view unmounted), reading .stateNode yields undefined, which passes the strict check and crashes in getFiberCurrentPropsFromNode with "Cannot read property 'canonical' of undefined". Loosen the check to `null == inst`, matching the surrounding event-plugin guards (`null != target`, `null == targetInst`), so the event is dropped for a dead target instead of throwing. Note: ReactFabric-* bundles are generated from facebook/react; the source counterpart is packages/react-native-renderer/src/ReactNativeGetListener.js (and its inlined copy in the responder plugin). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@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
Sep 9, 2026
@facebook-github-tools
facebook-github-tools
Bot
added
the
Shared with Meta
Applied via automation to indicate that an Issue or Pull Request has been shared with the team.
label
Sep 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
Fixes a production crash in the Fabric legacy event system:
getListenerguards the fiber'sstateNodewith a strict null check:Inside the reconciler this is sufficient —
stateNodeis initialized tonullin theFiberNodeconstructor, reset tonullindetachFiberAfterEffects(including thealternate), and only ever assigned instance objects in
completeWork— soundefinedcannot be produced by React itself.
However, the responder event path receives its target from native dispatch across the
JSI boundary. The instance handle is stored natively as a weak reference
(
EventTarget/InstanceHandle, where a deadjsi::WeakObject::lock()yieldsundefinedrather thannull), so when a touch is delivered for a view that unmountedmid-gesture (screen transition on press, sheet dismissal, list cell recycling), the
target reaching the plugins is no longer guaranteed to be a live host fiber. Reading
.stateNodeon such a target yieldsundefined, which passes the strict=== nullcheck and crashes one line later in
getFiberCurrentPropsFromNodewith the error above.This change loosens the check to
null == inst, matching the guards already used at theother entry points of the same pipeline (
null != targetindispatchEvent,null == targetInstinReactNativeBridgeEventPlugin.extractEvents). With the guard,the event for a dead target is dropped instead of throwing.
We are seeing this crash in production (React Native 0.84.0, Hermes, new architecture)
reported to Sentry as an unhandled error, correlated with touches during unmount.
Note:
ReactFabric-{dev,prod,profiling}.jsare generated bundles synced fromfacebook/react — the source counterpart of this fix is
packages/react-native-renderer/src/ReactNativeGetListener.js(and its inlined copy inResponderEventPlugin). Happy to redirect this patch there if that is the preferredroute; filing here first since the crash manifests in React Native releases.
Changelog:
[GENERAL] [FIXED] - Fix "Cannot read property 'canonical' of undefined" crash in Fabric event dispatch when a touch is delivered to a view unmounted mid-gesture
Test Plan:
undefinedcannot originate from the reconcileritself (
FiberNodeconstructor,detachFiberAfterEffects, and everystateNodeassignment in
completeWorkonly ever produce an object ornull), so the loosenedcheck only affects out-of-contract targets coming from native dispatch — for which
every sibling guard in this pipeline already uses loose null checks.
stateNodeguard in the two inlined copies ofgetListener(responder plugin + plugin registry) in each of the three generatedbundles; the subsequent props guard is untouched.
yarn jest react-nativepasses.event is processed (e.g. navigation triggered by the same interaction, or a recycled
list removing the row). Before this change the dispatch throws the TypeError above;
after it, the stale touch is ignored.