hibernate/hibernate-orm · error · TreatException
Fk paths cannot be TREAT-ed
Error message
Fk paths cannot be TREAT-ed
What it means
The result of fk() is a synthetic expression over the FK column(s), not a domain path with type identity, so SqmFkExpression.treatAs(Class) unconditionally throws TreatException. TREAT must be applied to the underlying entity association, not to the extracted key value.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmFkExpression.java:91
}
@Override
public SqmFkExpression<T> copy(SqmCopyContext context) {
final var existing = context.getCopy( this );
if ( existing != null ) {
return existing;
}
final var lhsCopy = (SqmEntityValuedSimplePath<?>) getLhs().copy( context );
return context.registerCopy(
this,
new SqmFkExpression<>( getNavigablePathCopy( lhsCopy ), lhsCopy )
);
}
@Nonnull
@Override
public <S extends T> SqmTreatedPath<T,S> treatAs(@Nonnull Class<S> treatJavaType) {
throw new TreatException( "Fk paths cannot be TREAT-ed" );
}
@Nonnull
@Override
public <S extends T> SqmTreatedPath<T,S> treatAs(@Nonnull EntityDomainType<S> treatTarget) {
throw new TreatException( "Fk paths cannot be TREAT-ed" );
}
@Override
public SqmPath<?> resolvePathPart(String name, boolean isTerminal, SqmCreationState creationState) {
final var sqmPath = get( name, true );
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
return sqmPath;
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Apply TREAT to the association path first, then extract the FK if needed: fk(treat(p.pet as Dog)) or simply join treat(p.pet as Dog) d
- Rewrite the query to join and treat the association, putting conditions on the joined alias
- If you only need the FK value, call fk() on the untreated association: fk(p.pet)
Example fix
// before from Person p join treat(fk(p.pet) as Dog) d // after from Person p join treat(p.pet as Dog) d // if you need the raw FK value: select fk(treat(p.pet as Dog)) from Person p
Defensive patterns
Strategy: type-guard
Type guard
static boolean supportsTreat(SqmExpression<?> expr) {
return !(expr instanceof SqmFkExpression<?>);
} Try / catch
try {
treated = expr.treatAs(target);
} catch (TreatException e) {
// expr was an fk() result: re-apply treat on the underlying association instead
throw new IllegalStateException("TREAT the to-one association before fk(), not after", e);
} Prevention
- Never apply TREAT to the result of fk(); treat the association first
- Keep fk() as the outermost operation in an expression
- In shared query helpers, instanceof-check SqmFkExpression before treatAs
When it happens
Trigger: HQL 'treat(fk(p.pet) as Dog)' or criteria code calling fkExpression.treatAs(Dog.class) on the result of the fk() function.
Common situations: Trying to combine Hibernate's fk() optimization with entity downcasting in one expression; criteria wrappers that automatically treat paths supplied by users; copy-pasting a TREAT pattern onto an fk() expression.
Related errors
- Cannot apply TREAT operator to discriminator path
- Non-aggregate composite paths cannot be TREAT-ed
- Basic-value cannot be treated (downcast)
- Derived roots can not be treated
- Embeddable paths cannot be TREAT-ed to an entity type
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/cc13aa2c6b890057.
Report an issue: GitHub.