hibernate/hibernate-orm · error · HibernateException
Could not instantiate event listener '{}'
Error message
Could not instantiate event listener '{}' What it means
Hibernate throws this while a SessionFactory initializes, when it cannot reflectively instantiate a custom event listener. Listeners are registered via properties named hibernate.event.listener.<event-type> (e.g. hibernate.event.listener.load) whose value is a comma-separated list of fully-qualified class names; MetadataImpl.initSessionFactory loads each class with ClassLoaderService and calls its no-arg constructor. Any failure (class not found, no public no-arg constructor, abstract class, or a constructor that throws) is wrapped in this HibernateException with the original cause attached.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java:528
EventType<T> eventType) {
final var eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
for ( String listenerImpl : splitAtCommas( listeners ) ) {
final var listener = instantiate( listenerImpl, classLoaderService );
final var baseListenerInterface = eventType.baseListenerInterface();
if ( !baseListenerInterface.isInstance( listener ) ) {
throw new HibernateException( "Event listener '" + listenerImpl
+ "' must implement '" + baseListenerInterface.getName() + "'");
}
eventListenerGroup.appendListener( baseListenerInterface.cast( listener ) );
}
}
private static Object instantiate(String listenerImpl, ClassLoaderService classLoaderService) {
try {
return classLoaderService.classForName( listenerImpl ).newInstance();
}
catch (Exception e) {
throw new HibernateException( "Could not instantiate event listener '" + listenerImpl + "'", e );
}
}
@Override
public void visitRegisteredComponents(Consumer<Component> consumer) {
composites.forEach( consumer );
}
@Override
public Component getGenericComponent(Class<?> componentClass) {
return genericComponentsMap.get( componentClass );
}
@Override
public DiscriminatorType<?> resolveEmbeddableDiscriminatorType(
Class<?> embeddableClass,
Supplier<DiscriminatorType<?>> supplier) {
return embeddableDiscriminatorTypesMap.computeIfAbsent( embeddableClass, k -> supplier.get() );View on GitHub (pinned to fad1729dce)
Solutions
- Check the exact fully-qualified class name in the hibernate.event.listener.<event-type> property and that the class is on the runtime classpath
- Give the listener a public no-argument constructor (classForName(...).newInstance() requires it)
- Unwrap and inspect the nested cause: ClassNotFoundException means classpath/typo, InvocationTargetException means the constructor itself threw
- If the listener needs dependencies, use a no-arg constructor with lazy lookup or register the listener programmatically via EventListenerRegistry instead of the property
- Verify in a scratch test: Class.forName(name).getConstructor().newInstance()
Example fix
// before: hibernate.cfg.xml property
// hibernate.event.listener.load = com.acme.AuditLoadListener
// where AuditLoadListener only defines AuditLoadListener(DataSource ds)
// after: add a public no-arg constructor to the listener
public AuditLoadListener() {
this.dataSource = DataSourceHolder.lookup(); // lazy, no injection needed
}
public AuditLoadListener(DataSource ds) {
this.dataSource = ds;
} Defensive patterns
Strategy: validation
Validate before calling
// before building the SessionFactory, check every configured listener
static void checkEventListeners(Properties props) throws Exception {
for (String name : props.stringPropertyNames()) {
if (!name.startsWith("hibernate.event.listener.")) continue;
for (String cls : props.getProperty(name).split(",")) {
Class<?> c = Class.forName(cls.trim());
if (c.isInterface() || Modifier.isAbstract(c.getModifiers()))
throw new IllegalStateException("Listener is abstract/interface: " + cls);
c.getConstructor(); // fails fast without public no-arg ctor
}
}
} Type guard
static boolean isInstantiableListener(String fqcn) {
try {
Class<?> c = Class.forName(fqcn);
return !c.isInterface() && !Modifier.isAbstract(c.getModifiers())
&& java.lang.reflect.Modifier.isPublic(c.getConstructor().getModifiers());
} catch (ReflectiveOperationException e) { return false; }
} Try / catch
try {
SessionFactory sf = metadata.buildSessionFactory();
} catch (HibernateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Could not instantiate event listener")) {
Throwable cause = e.getCause();
// ClassNotFoundException -> classpath/typo; InvocationTargetException -> ctor bug
log.error("Bad event listener config: {}", cause, e);
}
throw e;
} Prevention
- Keep a single constant for each listener FQCN used in properties so renames stay consistent
- Prefer registering listeners programmatically via EventListenerRegistry (Integrator) over string properties
- Give every listener a public no-arg constructor and resolve collaborators lazily
- Add a SessionFactory-bootstrap integration test so bad listener config fails in CI, not in production
When it happens
Trigger: SessionFactory bootstrap scans all settings starting with 'hibernate.event.listener.' and calls classLoaderService.classForName(listenerImpl).newInstance(); the error fires when the class is missing from the classpath, is abstract or an interface, has no accessible no-arg constructor, or its constructor throws an exception.
Common situations: Listener class renamed/moved during an upgrade but the property still holds the old name; listener lives in a module not deployed with the persistence unit; constructor expects injected dependencies and throws NPE; typo in the class name; property copied from another application where the class exists.
Related errors
- Unable to instantiate specified event listener class:
- Unable to instantiate StatementObserver - {}
- Could not instantiate named dialect class [%s]
- Unable to instantiate named dialect resolver [<resolverImplN
- Unable to instantiate specified BeanContainer
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/2b5f412981e7b65c.
Report an issue: GitHub.