hibernate/hibernate-orm · error · UnsupportedOperationException
Function joins can not be treated
Error message
Function joins can not be treated
What it means
SqmFunctionJoin models a join to the result of a set-returning function (`join unnest(...)`, `join generate_series(...)`, criteria JpaFrom.join(JpaSetReturningFunction)). The joined tuple is function output, not a persistent entity with an inheritance hierarchy — even createCorrelation() is unimplemented in this class. Consequently every treatAs overload, including this public criteria-facing treatAs(Class<S>), throws UnsupportedOperationException the moment it is called during query construction.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/from/SqmFunctionJoin.java:192
@Override
public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitQualifiedFunctionJoin( this );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA
@Override
@Nonnull
public SqmCorrelation<Object, E> createCorrelation() {
throw new UnsupportedOperationException();
}
@Nonnull
@Override
public <S extends E> SqmTreatedJoin<Object, E, S> treatAs(@Nonnull Class<S> treatTarget) {
throw new UnsupportedOperationException( "Function joins can not be treated" );
}
@Nonnull
@Override
public <S extends E> SqmTreatedJoin<Object, E, S> treatAs(@Nonnull EntityDomainType<S> treatTarget) {
throw new UnsupportedOperationException( "Function joins can not be treated" );
}
@Override
@Nonnull
public <S extends E> SqmTreatedJoin<Object, E, S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias) {
throw new UnsupportedOperationException( "Function joins can not be treated" );
}
@Override
@Nonnull
public <S extends E> SqmTreatedJoin<Object, E, S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias) {
throw new UnsupportedOperationException( "Function joins can not be treated" );View on GitHub (pinned to fad1729dce)
Solutions
- Remove the treat on the function join: project the key from the function output and join the entity separately (`join unnest(:ids) i join Employee e on e.id = i.value`), then treat that entity join.
- Consume the function output as its declared element type; a downcast to an entity subtype is never valid on function output.
- If entity-typed rows are needed, wrap the function in a subquery that selects entities and join the derived result instead.
Example fix
-- before: treat on a function join -> Function joins can not be treated select treat(u as Manager).salary from Client c join unnest(c.managerIds) u -- after: unnest yields ids; join and treat the entity side instead select treat(e as Manager).salary from Client c join unnest(c.managerIds) i join Employee e on e.id = i.value
Defensive patterns
Strategy: type-guard
Validate before calling
import org.hibernate.query.sqm.tree.spi.from.*;
if ( join instanceof SqmFunctionJoin<?> ) {
throw new IllegalArgumentException(
"TREAT is unsupported on function joins; join the entity separately and treat that join" );
} Type guard
static boolean supportsTreat(Join<?, ?> join) {
return !( join instanceof SqmFunctionJoin<?> )
&& !( join instanceof SqmDerivedJoin<?> )
&& !( join instanceof SqmCteJoin<?> );
} Try / catch
try {
treated = ( (JpaJoin<?, ?>) join ).treatAs( Sub.class );
} catch ( UnsupportedOperationException e ) {
if ( e.getMessage() != null && e.getMessage().startsWith( "Function joins" ) ) {
throw new QueryConstructionException(
"TREAT unsupported on function join " + join.getAlias()
+ "; project ids from the function and join the entity", e );
}
throw e;
} Prevention
- Treat joins model an entity; function output is scalar — keep them separate.
- Pattern: unnest ids, then join the entity on that id, then treat the entity join.
- Branch on join kind in generic treat helpers before calling treatAs(Class).
- Add function joins to the fixture set of any query-DSL layer that applies treats.
When it happens
Trigger: Calling treatAs(Class) on a JpaFunctionJoin: `JpaFunctionJoin<Long> g = root.join(cb.generateSeries(1, 10)); g.treatAs(MyEntity.class);`, or an HQL treat expression over a function-join alias (`treat(i as SubType)` where i comes from `join unnest(:ids) i`).
Common situations: Unnesting arrays/collections of entity ids and trying to downcast the unnest result directly; generic criteria wrappers calling treatAs(Class) on any join; adopting Hibernate 7 set-returning functions in queries that previously joined entity collections with TREAT.
Related errors
- CTE joins can not be treated
- Derived joins can not be treated
- Entity join treats can not be aliased
- Lateral joins can only be left or inner. Illegal join type:
- Lateral joins can only be left or inner. Illegal join type:
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/fd1b19b8de5b0109.
Report an issue: GitHub.