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

  1. Pass EntityManager.class for regular session work: runInTransaction(EntityManager.class, em -> ...)
  2. Pass EntityAgent.class when you want stateless-session semantics: runInTransaction(EntityAgent.class, agent -> ...)
  3. If you need a custom facade, wrap the EntityManager inside the lambda instead of passing your own class as handlerType
  4. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/941f536e343e265e. Report an issue: GitHub.