facebook/react · error · Error
233
233
Error message
Unsupported top level event type "${topLevelType}" dispatched What it means
React Native's legacy event bridge resolves each incoming native top-level event name against the view-config-derived customBubblingEventTypes / customDirectEventTypes registries; a name present in neither throws at extractEvents time. Concretely, the native side dispatched an event that JS never registered because its ViewManager does not declare it.
Source
Thrown at packages/react-native-renderer/src/ReactNativeBridgeEventPlugin.js:186
const ReactNativeBridgeEventPlugin: LegacyPluginModule<AnyNativeEvent> = {
eventTypes: {} as EventTypes,
extractEvents: function (
topLevelType: TopLevelType,
targetInst: null | Object,
nativeEvent: AnyNativeEvent,
nativeEventTarget: null | Object,
): ?Object {
if (targetInst == null) {
// Probably a node belonging to another renderer's tree.
return null;
}
const bubbleDispatchConfig = customBubblingEventTypes[topLevelType];
const directDispatchConfig = customDirectEventTypes[topLevelType];
if (!bubbleDispatchConfig && !directDispatchConfig) {
throw new Error(
// $FlowFixMe[incompatible-type] - Flow doesn't like this string coercion because DOMTopLevelEventType is opaque
`Unsupported top level event type "${topLevelType}" dispatched`,
);
}
const event = SyntheticEvent.getPooled(
bubbleDispatchConfig || directDispatchConfig,
targetInst,
nativeEvent,
nativeEventTarget,
);
if (bubbleDispatchConfig) {
const skipBubbling =
event != null &&
event.dispatchConfig.phasedRegistrationNames != null &&
event.dispatchConfig.phasedRegistrationNames.skipBubbling;
if (skipBubbling) {
accumulateCapturePhaseDispatches(event);View on GitHub (pinned to eafeac097b)
Solutions
- Declare the event in the native ViewManager (e.g. the codegen events array with the exact top-prefixed name being dispatched) and rebuild the app.
- Verify the event name matches on both sides, case-sensitive, including the top prefix used for registration.
- If the target node may belong to another renderer, guard the dispatch on the native side - targetInst == null is ignored, but unregistered event names are not.
Example fix
// before - native view emits 'quantityChanged' but never declares it
// (RCTEventEmitter receiveEvent(..., 'quantityChanged', ...))
// after - declare it in the codegen spec so JS registers it
// NativeCounter.js
export default codegenNativeComponent('Counter', {
interfaceName: 'RCTCounter',
events: [{name: 'topQuantityChanged', bubbling: false}],
}); Defensive patterns
Strategy: validation
Validate before calling
import {UIManager} from 'react-native';
function isEventRegistered(viewName, eventName) {
const viewConfig = UIManager.getViewManagerConfig(viewName);
return Boolean(
viewConfig?.Manager?.directEventTypes?.[eventName] ||
viewConfig?.Manager?.bubblingEventTypes?.[eventName],
);
}
if (!isEventRegistered('Counter', 'topQuantityChanged')) {
throw new Error(
'Declare topQuantityChanged on the native ViewManager before dispatching it',
);
} Prevention
- Declare every dispatched event in the native ViewManager's codegen spec with the exact top-prefixed name.
- Rebuild the native app and clear Metro cache after changing event declarations.
- Keep iOS and Android event name constants identical.
When it happens
Trigger: A native view dispatches an event whose name is not declared in its ViewManager's event tables: a custom native component emitting an event without registering it (codegen directEvents/bubblingEvents), a casing or spelling mismatch between the native constant and the dispatched name, or an event sent for a node owned by another renderer.
Common situations: Custom native modules; adding a native event but not rebuilding/regenerating native code; Fabric codegen event-name differences between iOS and Android; typos in the 'top'-prefixed event constant.
Related errors
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/03deed5367632e0f.
Report an issue: GitHub.