hibernate/hibernate-orm · error · IllegalArgumentException
Unknown EntityHandler type passed : {handlerType.getName()}
Error message
Unknown EntityHandler type passed : {handlerType.getName()} What it means
SessionFactory.runInTransaction(Class<H>, Consumer<H>) executes work with an EntityHandler of your choosing, but only two families exist: EntityManager (ORM session work) and EntityAgent (stateless session work). The method dispatches with isAssignableFrom on those two and throws IllegalArgumentException for anything else, so the handlerType must be the EntityManager/EntityAgent interfaces themselves or a subtype.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java:1285
@Override
public void runInTransaction(@Nonnull Consumer<EntityManager> work) {
inTransaction( work );
}
@Override
public <H extends EntityHandler> void runInTransaction(
@Nonnull Class<H> handlerType, @Nonnull Consumer<H> consumer) {
if ( EntityManager.class.isAssignableFrom( handlerType ) ) {
//noinspection unchecked
inTransaction( (Consumer<EntityManager>) consumer );
}
else if ( EntityAgent.class.isAssignableFrom( handlerType ) ) {
//noinspection unchecked
inStatelessTransaction( (Consumer<EntityAgent>) consumer );
}
else {
throw new IllegalArgumentException( "Unknown EntityHandler type passed : " + handlerType.getName() );
}
}
@Override
public <R> R callInTransaction(@Nonnull Function<EntityManager, R> work) {
return fromTransaction( work );
}
@Override
public <R, H extends EntityHandler> R callInTransaction(
@Nonnull Class<H> handlerType, @Nonnull Function<H, R> function) {
if ( EntityManager.class.isAssignableFrom( handlerType ) ) {
//noinspection unchecked
return fromTransaction( (Function<EntityManager,R>) function );
}
else if ( EntityAgent.class.isAssignableFrom( handlerType ) ) {
//noinspection unchecked
return fromStatelessTransaction( (Function<EntityAgent,R>) function );View on GitHub (pinned to fad1729dce)
Solutions
- Pass EntityManager.class for regular session work: runInTransaction(EntityManager.class, em -> ...)
- Pass EntityAgent.class when you want stateless-session semantics: runInTransaction(EntityAgent.class, agent -> ...)
- If you need a custom facade, wrap the EntityManager inside the lambda instead of passing your own class as handlerType
- Guard custom dispatch code with the same isAssignableFrom checks before calling the API
Example fix
// before
public interface OrderRepo { void saveAll(List<Order> orders); }
sessionFactory.runInTransaction(OrderRepo.class, repo -> ...); // IllegalArgumentException
// after
sessionFactory.runInTransaction(EntityManager.class, em -> {
OrderRepo repo = new OrderRepoImpl(em); // wrap inside the lambda
repo.saveAll(orders);
}); Defensive patterns
Strategy: type-guard
Validate before calling
if (!EntityManager.class.isAssignableFrom(handlerType)
&& !EntityAgent.class.isAssignableFrom(handlerType)) {
throw new IllegalArgumentException(
"handlerType must be EntityManager or EntityAgent, got " + handlerType.getName());
}
sessionFactory.runInTransaction(handlerType, consumer); Type guard
static boolean isSupportedHandler(Class<? extends EntityHandler> t) {
return EntityManager.class.isAssignableFrom(t)
|| EntityAgent.class.isAssignableFrom(t);
} Try / catch
try {
sessionFactory.runInTransaction(handlerType, consumer);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Unknown EntityHandler type")) {
// default to EntityManager semantics
sessionFactory.runInTransaction(EntityManager.class, em -> consumer.accept((H) em));
} else throw e;
} Prevention
- Pass exactly EntityManager.class or EntityAgent.class — the two supported constants
- Build custom facades inside the lambda instead of inventing new handler types
- Wrap generic dispatch code with the isAssignableFrom guard to fail with a clearer message
When it happens
Trigger: Calling sessionFactory.runInTransaction(handlerType, consumer) where handlerType is neither EntityManager.class/EntityAgent.class nor a subclass — e.g. a custom interface, a mock class, or Object.class.
Common situations: Framework/abstraction code parameterizing the handler type generically and passing an arbitrary user interface; tests passing mock handler classes; discovering the new in-transaction API (Hibernate 7) and experimenting with custom handler types.
Related errors
- immutable global instance of LockOptions
- json_object must have an even number of arguments, but found
- Length must be great-than-or-equal to zero.
- Length must be great-than-or-equal to zero.
- Length must be greater than or equal to zero
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/941f536e343e265e.
Report an issue: GitHub.