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

  1. 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
  2. Rewrite the query to join and treat the association, putting conditions on the joined alias
  3. 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

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


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