{"record":{"id":"e0683f0e47431e6a","repo":"facebook/react","slug":"98","errorCode":"98","errorMessage":"EventPluginRegistry: Failed to publish event `${eventName}` for plugin `${pluginName}`.","messagePattern":"EventPluginRegistry: Failed to publish event `(.+?)` for plugin `(.+?)`\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-native-renderer/src/legacy-events/EventPluginRegistry.js","lineNumber":76,"sourceCode":"\n    if (!pluginModule.extractEvents) {\n      throw new Error(\n        'EventPluginRegistry: Event plugins must implement an `extractEvents` ' +\n          `method, but \\`${pluginName}\\` does not.`,\n      );\n    }\n\n    plugins[pluginIndex] = pluginModule;\n    const publishedEvents = pluginModule.eventTypes;\n    for (const eventName in publishedEvents) {\n      if (\n        !publishEventForPlugin(\n          publishedEvents[eventName],\n          pluginModule,\n          eventName,\n        )\n      ) {\n        throw new Error(\n          `EventPluginRegistry: Failed to publish event \\`${eventName}\\` for plugin \\`${pluginName}\\`.`,\n        );\n      }\n    }\n  }\n}\n\n/**\n * Publishes an event so that it can be dispatched by the supplied plugin.\n *\n * @param {object} dispatchConfig Dispatch configuration for the event.\n * @param {object} PluginModule Plugin publishing the event.\n * @return {boolean} True if the event was successfully published.\n * @private\n */\nfunction publishEventForPlugin(\n  dispatchConfig: DispatchConfig,\n  pluginModule: LegacyPluginModule<AnyNativeEvent>,","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-native-renderer/src/legacy-events/EventPluginRegistry.js#L58-L94","documentation":"When publishing a plugin's eventTypes, publishEventForPlugin only succeeds if the dispatchConfig declares phasedRegistrationNames or a registrationName - otherwise the registry throws 'Failed to publish event ... for plugin ...' because the event could never be dispatched to a listener prop. (A duplicate event name would instead throw the separate 'More than one plugin' error.)","triggerScenarios":"An injected plugin whose eventTypes entry has neither phasedRegistrationNames (captured/bubbled) nor registrationName - e.g. a hand-written or incompletely ported eventType config with only dependencies or custom fields.","commonSituations":"Hand-written plugin event configs; plugins copied from a different event system that uses different field names (e.g. only a name field); refactors that drop the registration fields.","solutions":["Give the eventType a valid dispatch target: either registrationName: 'onMyEvent' or phasedRegistrationNames: {captured: 'onMyEventCapture', bubbled: 'onMyEvent'}.","Cross-check the field names against an existing plugin (e.g. ResponderEventPlugin) registered in the same registry.","Re-inject after fixing - the registry validates at injection time, so errors surface immediately."],"exampleFix":"// before\nMyPlugin.eventTypes = {\n  MyGesture: {dependencies: ['topTouchStart']},\n};\n\n// after\nMyPlugin.eventTypes = {\n  MyGesture: {\n    phasedRegistrationNames: {\n      captured: 'onMyGestureCapture',\n      bubbled: 'onMyGesture',\n    },\n    dependencies: ['topTouchStart'],\n  },\n};","handlingStrategy":"validation","validationCode":"const hasDispatchTarget = config =>\n  Boolean(config.phasedRegistrationNames || config.registrationName);\nfor (const [eventName, config] of Object.entries(MyPlugin.eventTypes)) {\n  if (!hasDispatchTarget(config)) {\n    throw new Error(\n      `eventType '${eventName}' needs phasedRegistrationNames or registrationName`,\n    );\n  }\n}\ninjectEventPluginsByName({MyPlugin});","typeGuard":"const isValidDispatchConfig = config =>\n  config != null &&\n  Boolean(config.phasedRegistrationNames || config.registrationName);","tryCatchPattern":null,"preventionTips":["Give every eventType either registrationName or phasedRegistrationNames (captured/bubbled).","Copy the field structure of a known plugin (e.g. ResponderEventPlugin) when writing new ones.","Remember the registry validates at injection time - test injection in dev startup, not lazily."],"tags":["react-native","legacy-events","event-plugins","event-registration"],"backgroundTag":"event-plugin-registration-mismatch","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}