hibernate/hibernate-orm · error · UnsupportedOperationException
Derived joins can not be treated
Error message
Derived joins can not be treated
What it means
SqmDerivedJoin models a join to a subquery result: HQL `join (select ...) d on ...`, criteria `JpaFrom.join(Subquery)` / `joinLateral(...)`. The joined thing is an anonymous query result, not a metamodel entity type — SqmDerivedJoin.getAttribute() returns null — so there is no inheritance hierarchy to downcast. Every treatAs overload, including this public criteria-facing treatAs(Class<S>), throws UnsupportedOperationException at query-construction time.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/from/SqmDerivedJoin.java:198
@Override
public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitQualifiedDerivedJoin( this );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA
@Override
@Nonnull
public SqmCorrelatedDerivedJoin<T> createCorrelation() {
return new SqmCorrelatedDerivedJoin<>( this );
}
@Nonnull
@Override
public <S extends T> SqmTreatedJoin<T, T, S> treatAs(@Nonnull Class<S> treatTarget) {
throw new UnsupportedOperationException( "Derived joins can not be treated" );
}
@Nonnull
@Override
public <S extends T> SqmTreatedJoin<T, T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget) {
throw new UnsupportedOperationException( "Derived joins can not be treated" );
}
@Override
@Nonnull
public <S extends T> SqmTreatedJoin<T, T, S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias) {
throw new UnsupportedOperationException( "Derived joins can not be treated" );
}
@Override
@Nonnull
public <S extends T> SqmTreatedJoin<T, T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias) {
throw new UnsupportedOperationException( "Derived joins can not be treated" );View on GitHub (pinned to fad1729dce)
Solutions
- Remove the treatAs and make the subquery select the concrete subtype (`select m from Manager m ...`) so the derived join is already correctly typed.
- Join the target entity directly with an attribute/entity join (where treat is supported) and express the correlation via on/where predicates instead of joining the subquery result.
- In dynamic query builders, branch on the join kind (skip treat for JpaDerivedJoin) instead of calling treatAs unconditionally.
Example fix
// before - UnsupportedOperationException: Derived joins can not be treated JpaDerivedJoin<Employee> d = root.join( employeesSubquery ); d.treatAs( Manager.class ); // after - the subquery selects Manager, so the derived join needs no downcast JpaSubQuery<Manager> managerSub = query.subquery( Manager.class ); JpaRoot<Manager> m = managerSub.from( Manager.class ); managerSub.select( m ).where( cb.equal( m.get( "department" ), root.get( "department" ) ) ); JpaDerivedJoin<Manager> d = root.join( managerSub );
Defensive patterns
Strategy: type-guard
Validate before calling
import org.hibernate.query.sqm.tree.spi.from.*;
if ( join instanceof SqmDerivedJoin<?> ) {
throw new IllegalArgumentException(
"TREAT is unsupported on derived (subquery) joins; select the subtype inside the subquery" );
} Type guard
static boolean supportsTreat(Join<?, ?> join) {
// derived joins are anonymous result shapes - only attribute/roots can be treated
return !( join instanceof SqmDerivedJoin<?> )
&& !( join instanceof SqmCteJoin<?> )
&& !( join instanceof SqmFunctionJoin<?> );
} Try / catch
try {
treated = ( (JpaJoin<?, ?>) join ).treatAs( Sub.class );
} catch ( UnsupportedOperationException e ) {
if ( e.getMessage() != null && e.getMessage().contains( "Derived joins" ) ) {
throw new QueryConstructionException(
"TREAT unsupported on derived join " + join.getAlias()
+ "; type the subquery result instead", e );
}
throw e;
} Prevention
- Make subqueries select the concrete subtype so derived joins never need treat.
- Reserve treatAs for attribute joins of polymorphic entities.
- Branch on join kind in dynamic builders before applying treatAs(Class).
- When converting an entity join to a subquery join, delete its TREAT clauses in the same change.
When it happens
Trigger: Calling treatAs(Class) on a JpaDerivedJoin: `JpaDerivedJoin<Employee> d = root.join(subquery); d.treatAs(Manager.class);` — or an HQL treat path expression over a derived-join alias such as `treat(d as Manager).salary`.
Common situations: Replacing an entity attribute join with a subquery join (dedup, limits, aggregates) while keeping a TREAT from the old query; generic criteria wrappers that call treatAs(Class) on arbitrary joins; Hibernate 6.x to 7 migration moving these classes to the spi.from package.
Related errors
- CTE joins can not be treated
- Lateral joins can only be left or inner. Illegal join type:
- Entity join treats can not be aliased
- Function joins can not be treated
- Correlated derived root does not have an entity type. Use ge
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b395b0c1c7d0f9b9.
Report an issue: GitHub.