hibernate/hibernate-orm · error · IllegalStateException

The JPA specification does not permit specifying an alias fo

Error message

The JPA specification does not permit specifying an alias for fetch joins.

What it means

AbstractSqmAttributeJoin.alias(String) validates aliases of fetch joins: when the join is a fetch join, an alias is set, it does not start with Hibernate's internal 'var_' prefix, and JPA query compliance (hibernate.jpa.compliance.query) is enabled, it throws IllegalStateException because the JPA specification forbids assigning aliases to fetch joins. With compliance disabled (the default) arbitrary fetch aliases are allowed as a Hibernate extension.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/AbstractSqmAttributeJoin.java:102

		return fetchJoin;
	}

	@Override
	@Nonnull
	public SqmAttributeJoin<L,R> alias(@Nonnull String name) {
		validateFetchAlias( name, fetchJoin, nodeBuilder() );
		return (SqmAttributeJoin<L, R>) super.alias( name );
	}

	@Override
	public void clearFetched() {
		fetchJoin = false;
	}

	private static void validateFetchAlias(@Nullable String alias, boolean fetchJoin, NodeBuilder nodeBuilder) {
		if ( fetchJoin && alias != null && !alias.startsWith( "var_" )
				&& nodeBuilder.isJpaQueryComplianceEnabled() ) {
			throw new IllegalStateException(
					"The JPA specification does not permit specifying an alias for fetch joins."
			);
		}
	}

	@Override
	public <X> X accept(SemanticQueryWalker<X> walker) {
		return walker.visitQualifiedAttributeJoin( this );
	}


	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// JPA

	@Override
	public @Nonnull PersistentAttribute<? super L, ?> getAttribute() {
		//noinspection unchecked
		return (PersistentAttribute<? super L, ?>) getModel();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove the alias from the fetch join; reference the fetched attribute through the owning root path instead.
  2. If you need to sort/filter on the association, use a real join (root.join(...)) rather than fetch, alias that, and mark the fetch separately if eager fetching is required.
  3. As a Hibernate-specific escape hatch, prefix the alias with 'var_' (the generated-alias prefix is exempt).
  4. Turn off the setting: hibernate.jpa.compliance.query=false.

Example fix

// before (compliance on)
root.fetch( "items", JoinType.LEFT ).alias( "i" );
cb.desc( root.get( "items" ).get( "createdOn" ) );
// after
root.fetch( "items", JoinType.LEFT );
cb.desc( root.join( "items", JoinType.LEFT ).get( "createdOn" ) );
Defensive patterns

Strategy: validation

Validate before calling

static void aliasSafely(JpaFetch<?, ?> fetch, String alias, NodeBuilder cb) {
    if ( cb.isJpaQueryComplianceEnabled() ) {
        return; // skip aliasing under JPA compliance
    }
    fetch.alias( alias );
}

Type guard

static boolean aliasAllowedOnFetch(boolean fetchJoin, String alias, boolean jpaCompliance) {
    return !fetchJoin || alias == null || alias.startsWith( "var_" ) || !jpaCompliance;
}

Prevention

When it happens

Trigger: root.fetch("items").alias("i") or fetch(attribute, joinType).alias(name) while the persistence unit sets hibernate.jpa.compliance.query=true; also aliasing a join that was marked fetched via fetch-join reuse.

Common situations: Enabling JPA query compliance for certification/portability in a codebase that aliases fetch joins (commonly to order by or to reference a fetched element's attribute); environment differences where one persistence unit sets the flag and another does not, so the code only breaks in the compliant environment.

Related errors


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