hibernate/hibernate-orm · error · IllegalArgumentException

Cross join treats can not be aliased

Error message

Cross join treats can not be aliased

What it means

TREAT AS turns a join into a subtype view, and an alias on a treat creates a new identification variable. SqmCrossJoin.treatAs(EntityDomainType, alias, fetch) throws IllegalArgumentException('Cross join treats can not be aliased') when alias != null, because the underlying cross join has no identification variable to attach the treat alias to. (The Class overload delegates with alias=null, fetch=false.)

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/from/SqmCrossJoin.java:208

	}

	@Override
	@Nonnull
	public <S extends T> SqmTreatedCrossJoin<L, T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias) {
		return treatAs( treatTarget, alias, false );
	}

	@Override
	@Nonnull
	public <S extends T> SqmTreatedCrossJoin<L, T, S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias, boolean fetch) {
		return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, false );
	}

	@Override
	@Nonnull
	public <S extends T> SqmTreatedCrossJoin<L, T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias, boolean fetch) {
		if ( alias != null ) {
			throw new IllegalArgumentException( "Cross join treats can not be aliased" );
		}
		if ( fetch ) {
			throw new IllegalArgumentException( "Cross join treats can not be fetched" );
		}
		final var treat = (SqmTreatedCrossJoin<L, T, S>) findTreat( treatTarget, null );
		if ( treat == null ) {
			return addTreat( new SqmTreatedCrossJoin<>( this, (SqmEntityDomainType<S>) treatTarget ) );
		}
		else {
			return treat;
		}
	}

	@Nonnull
	@Override
	public <S extends T> SqmTreatedCrossJoin<L, T, S> treatAs(@Nonnull Class<S> treatAsType) {
		return treatAs( treatAsType, null, false );
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use the alias-less form - crossJoin.treatAs(Sub.class) - and reference the returned treated node directly in predicates.
  2. If you need an aliased treat, replace the cross join with an explicit join, which supports aliased treats.
  3. In generic code, pass alias=null when the join is an SqmCrossJoin.

Example fix

// before
SqmTreatedCrossJoin<?, ?, Sub> t = crossJoin.treatAs( Sub.class, "sub" ); // IllegalArgumentException

// after
SqmTreatedCrossJoin<?, ?, Sub> t = crossJoin.treatAs( Sub.class );
cq.where( cb.equal( t.get( Sub_.code ), "X" ) );
Defensive patterns

Strategy: validation

Validate before calling

static boolean treatSupportsAlias(SqmJoin<?, ?> join) {
    return !( join instanceof SqmCrossJoin );
}
// usage:
join.treatAs( Sub.class, treatSupportsAlias( join ) ? "sub" : null, false );

Prevention

When it happens

Trigger: Criteria code calling crossJoin.treatAs(Sub.class, "sub") or the three-arg overload with a non-null alias; generic join-processing code that uniformly aliases every treatAs call without distinguishing join kinds.

Common situations: Reusing treatAs code written for explicit joins on a cross join; porting JPA Criteria treat() usage to Hibernate cross joins; HQL treat(...) with an alias applied to a cross-joined entity.

Related errors


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