{"record":{"id":"464309adc094dda3","repo":"hibernate/hibernate-orm","slug":"custom-event-type-already-registered","errorCode":null,"errorMessage":"Custom event-type already registered: ","messagePattern":"Custom event-type already registered: ","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/event/spi/EventEngine.java","lineNumber":118,"sourceCode":"\t\t@Nonnull\n\t\tpublic <T> EventType<T> contributeEventType(@Nonnull String name, @Nonnull Class<T> listenerRole) {\n\t\t\tfinal var eventType = registerEventType( name, listenerRole );\n\t\t\tlistenerRegistryBuilder.prepareListeners( eventType );\n\t\t\treturn eventType;\n\t\t}\n\n\t\t@Nonnull\n\t\tprivate <T> EventType<T> registerEventType(@Nonnull String name, @Nonnull Class<T> listenerRole) {\n\t\t\tif ( name == null ) {\n\t\t\t\tthrow new HibernateException( \"Custom event-type name must be non-null.\" );\n\t\t\t}\n\t\t\telse if ( listenerRole == null ) {\n\t\t\t\tthrow new HibernateException( \"Custom event-type listener role must be non-null.\" );\n\t\t\t}\n\t\t\t// make sure it does not match an existing name...\n\t\t\telse if ( eventTypes.containsKey( name ) ) {\n\t\t\t\tfinal var existing = eventTypes.get( name );\n\t\t\t\tthrow new HibernateException(\n\t\t\t\t\t\t\"Custom event-type already registered: \" + name + \" => \" + existing\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfinal EventType<T> eventType = EventType.create( name, listenerRole, eventTypes.size() );\n\t\t\t\teventTypes.put( name, eventType );\n\t\t\t\treturn eventType;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\t@Nonnull\n\t\t@SafeVarargs\n\t\tpublic final <T> EventType<T> contributeEventType(@Nonnull String name, @Nonnull Class<T> listenerRole, @Nonnull T... defaultListeners) {\n\t\t\tfinal var eventType = contributeEventType( name, listenerRole );\n\t\t\tif ( defaultListeners != null ) {\n\t\t\t\tlistenerRegistryBuilder.getListenerGroup( eventType ).appendListeners( defaultListeners );\n\t\t\t}","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/event/spi/EventEngine.java#L100-L136","documentation":"HibernateException from EventEngine's registerEventType: an event type with the given name is already present in the engine's map — the map holds both the standard types (registered via EventType.registerStandardTypes: load, flush, save, merge, ...) and previously contributed custom types, and names must be unique across both. The message includes the existing EventType that owns the name.","triggerScenarios":"An EventEngineContributor contributing a custom event type whose name collides with a standard one ('load', 'flush', 'persist', ...) or with another contributor's custom type; the same contributor being discovered twice (duplicate jar on the classpath / duplicated META-INF/services entries) so its contribution runs twice per SessionFactory build.","commonSituations":"Two versions of an integration library both shipping the same EventEngineContributor service; fat-jar/shading merging service files so the contributor lists twice; generic names like 'audit' or 'notify' colliding between first-party and third-party integrations.","solutions":["Namespace custom event-type names (e.g. 'com.acme.hr.audit') so they cannot collide with standard or other custom names","Before contributing, check findEventType(name) on the EventEngineContributions and skip or reuse when the name is already registered","Eliminate duplicate contributor discovery: inspect the fat jar's merged META-INF/services and run mvn dependency:tree to find doubled integration artifacts"],"exampleFix":"// before\npublic void contribute(EventEngineContributions c) {\n    c.contributeEventType(\"audit\", AuditListener.class); // collides with standard/other 'audit'\n}\n\n// after\npublic void contribute(EventEngineContributions c) {\n    if (c.findEventType(\"com.acme.audit\") == null) {\n        c.contributeEventType(\"com.acme.audit\", AuditListener.class);\n    }\n}","handlingStrategy":"validation","validationCode":"public void contribute(EventEngineContributions c) {\n    if (c.findEventType(\"com.acme.audit\") == null) {\n        c.contributeEventType(\"com.acme.audit\", MyAuditListener.class);\n    }\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Namespace custom event-type names with a package-style prefix","Check findEventType(name) before contributing to stay idempotent","Audit fat jars for merged META-INF/services entries that run contributors twice"],"tags":["hibernate","custom-event","duplicate","event-engine","classpath","service-loader"],"backgroundTag":"duplicate-registration-name","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}