hibernate/hibernate-orm · error · UnsupportedOperationException
Correlated derived root does not have an entity type. Use ge
Error message
Correlated derived root does not have an entity type. Use getReferencedPathSource() instead.
What it means
SqmCorrelatedDerivedRoot wraps a subquery root that was correlated into an inner query and whose outer referent is a derived root (a "from (select ...)" group, often created via SqmCteRoot.createCorrelation() or correlating a derived root inside a subquery). Such a root denotes query-derived rows, not a mapped entity, so the JPA Root contract getModel() (returning an EntityType) cannot be honored; Hibernate throws UnsupportedOperationException and the message tells you to use getReferencedPathSource() to inspect the row type instead.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmCorrelatedDerivedRoot.java:54
final var existing = context.getCopy( this );
if ( existing != null ) {
return existing;
}
final var path = context.registerCopy(
this,
new SqmCorrelatedDerivedRoot<>( getCorrelationParent().copy( context ) )
);
copyTo( path, context );
return path;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA
@Nonnull
@Override
public SqmEntityDomainType<T> getModel() {
throw new UnsupportedOperationException( "Correlated derived root does not have an entity type. Use getReferencedPathSource() instead." );
}
@Override
public String getEntityName() {
throw new UnsupportedOperationException( "Correlated derived root does not have an entity type. Use getReferencedPathSource() instead." );
}
@Override
public SqmPathSource<T> getResolvedModel() {
return getReferencedPathSource();
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Use getReferencedPathSource() (or getResolvedModel(), which delegates to it) to obtain the SqmPathSource describing the derived rows.
- Guard generic root-handling code: skip or special-case roots that are SqmDerivedRoot, SqmCteRoot, or SqmCorrelatedDerivedRoot before calling getModel().
- When an EntityType is genuinely required, query the underlying mapped entity directly instead of a derived table.
- Catch UnsupportedOperationException as a last resort in framework code and fall back to getJavaType() metadata.
Example fix
// before - breaks when the correlated root wraps a derived/CTE root
EntityType<?> t = (EntityType<?>) root.getModel();
String name = t.getName();
// after - ask for the referenced path source, which always exists
String name = ((org.hibernate.query.sqm.tree.spi.domain.SqmPath<?>) root)
.getReferencedPathSource().getPathName(); Defensive patterns
Strategy: type-guard
Validate before calling
// In generic root walkers, probe for entity-backed roots before using getModel()
static boolean hasEntityType(jakarta.persistence.criteria.Root<?> root) {
return !(root instanceof org.hibernate.query.sqm.tree.spi.domain.SqmCorrelatedDerivedRoot)
&& !(root instanceof org.hibernate.query.sqm.tree.spi.domain.SqmDerivedRoot)
&& !(root instanceof org.hibernate.query.sqm.tree.spi.domain.SqmCteRoot)
&& !(root instanceof org.hibernate.query.sqm.tree.spi.domain.SqmFunctionRoot);
} Type guard
static boolean isEntityBackedRoot(Object sqmRoot) {
return sqmRoot instanceof org.hibernate.query.sqm.tree.spi.from.SqmRoot
|| sqmRoot instanceof org.hibernate.query.sqm.tree.spi.from.SqmCrossJoin
|| sqmRoot instanceof org.hibernate.query.sqm.tree.spi.from.SqmEntityJoin;
} Try / catch
try {
return root.getModel();
} catch (UnsupportedOperationException e) {
// derived/CTE/correlated-derived roots: no EntityType available
return null; // caller falls back to getReferencedPathSource() / getJavaType()
} Prevention
- Never call getModel() unconditionally on roots received from arbitrary queries.
- Prefer getResolvedModel()/getReferencedPathSource() which works for all root kinds.
- Add CTE and derived-table queries to the corpus your framework tests against.
- Treat 'UnsupportedOperationException from getModel' as a missing-type-check code smell, not a runtime hazard to swallow.
When it happens
Trigger: HQL with a derived table correlated into a subquery, e.g. "select e from Employee e where exists (select 1 from (select ...) d where d.x = e.x)" combined with Java code that calls root.getModel() on the subquery root; Criteria code doing subquery.correlate(derivedRoot).getModel(); generic framework code (Specifications, auditors, entity-graph appliers) that unconditionally calls getModel() on every root of every query.
Common situations: Spring Data JPA or in-house specification layers that resolve root.getModel().getName() for aliasing or logging on arbitrary queries; migrating queries from entity roots to CTE/derived-table style (Hibernate 6.6+/7 improved support) and legacy root-processing code breaking; correlation of a CTE root (SqmCteRoot.createCorrelation returns SqmCorrelatedDerivedRoot).
Related errors
- Not correlated
- Correlated derived root does not have an entity type. Use ge
- Can't set alias on a correlated root
- Derived root does not have an entity type. Use getReferenced
- Derived roots can not be treated
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/e91a1d70ff85b664.
Report an issue: GitHub.