hibernate/hibernate-orm · error · SemanticException

Implicitly-polymorphic domain path in subquery '${name}'

Error message

Implicitly-polymorphic domain path in subquery '${name}'

What it means

A polymorphic root (SqmPolymorphicRootDescriptor) was used as the root of a subquery (processingStateStack.depth() > 1). Implicit polymorphism is only supported for top-level roots; Hibernate cannot enumerate the matching entity set for a nested domain path, so it throws SemanticException naming the polymorphic descriptor.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java:2130

		final var processingState = processingStateStack.getCurrent();
		final var pathRegistry = processingState.getPathRegistry();
		if ( entityDescriptor == null ) {
			return resolveRootEntity( entityNameContext, name, alias, processingState, pathRegistry );
		}
		checkFQNEntityNameJpaComplianceViolationIfNeeded( name, entityDescriptor );

		if ( entityDescriptor instanceof SqmPolymorphicRootDescriptor ) {
			if ( getCreationOptions().useStrictJpaCompliance() ) {
				throw new StrictJpaComplianceViolation(
						"Encountered unmapped polymorphic reference ["
								+ entityDescriptor.getHibernateEntityName()
								+ "], but strict JPQL compliance was requested",
						StrictJpaComplianceViolation.Type.UNMAPPED_POLYMORPHISM
				);
			}

			if ( processingStateStack.depth() > 1 ) {
				throw new SemanticException(
						"Implicitly-polymorphic domain path in subquery '" + entityDescriptor.getName() + "'",
						query
				);
			}
		}

		final var sqmRoot = new SqmRoot<>( entityDescriptor, alias, true, nodeBuilder() );
		pathRegistry.register( sqmRoot );
		return sqmRoot;
	}

	private SqmRoot<?> resolveRootEntity(
			HqlParser.EntityNameContext entityNameContext,
			String name, String alias,
			SqmCreationProcessingState processingState,
			SqmPathRegistry pathRegistry) {
		final var entityNameParseTreeChildren = entityNameContext.children;
		final int size = entityNameParseTreeChildren.size();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use a concrete entity name as the subquery root
  2. Move the polymorphic part to the outer query and correlate the concrete subquery
  3. Restructure the predicate so no polymorphic root is needed (e.g. member-of checks on associations)

Example fix

// before
select e from Employee e where exists (select 1 from java.lang.Object o where ...)

// after
select e from Employee e where exists (select 1 from Project p where p.lead = e)
Defensive patterns

Strategy: validation

Validate before calling

// Do not allow polymorphic/namespace names as subquery roots in generated HQL
static boolean subqueryRootIsConcrete(EntityManagerFactory emf, String rootName) {
    return emf.getMetamodel().getEntities().stream().anyMatch(e -> e.getName().equals(rootName));
}
if (!subqueryRootIsConcrete(emf, subqueryRoot)) throw new IllegalArgumentException("Use a concrete entity as subquery root: " + subqueryRoot);

Try / catch

try {
    return em.createQuery(hql, Employee.class).getResultList();
} catch (org.hibernate.query.sqm.SemanticException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Implicitly-polymorphic domain path in subquery")) {
        throw new IllegalArgumentException("Replace the polymorphic subquery root with a concrete entity", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: 'select e from Employee e where exists (select 1 from java.lang.Object o where ...)'; any subquery whose from-clause root is a namespace/polymorphic name.

Common situations: Reusing a working polymorphic top-level query as an exists/in-subquery; generic framework code that builds subqueries from user-supplied entity names.

Related errors


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