hibernate/hibernate-orm · error · UnsupportedOperationException

Can't set alias on a correlated root

Error message

Can't set alias on a correlated root

What it means

SqmCorrelatedRoot.setExplicitAlias throws UnsupportedOperationException because a correlated root does not own its alias: getExplicitAlias() delegates to the outer correlation parent, so mutating the alias on the inner copy would desynchronize the correlation. JPA's Root.alias(String) funnels into setExplicitAlias, so calling alias() on the root returned by Subquery.correlate(...) triggers this immediately. The alias must be managed on the outer parent root.

Source

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

	@Nonnull
	@Override
	public SqmRoot<T> getCorrelationParent() {
		return correlationParent;
	}

	@Override
	public SqmPath<T> getWrappedPath() {
		return getCorrelationParent();
	}

	@Override
	public @Nullable String getExplicitAlias() {
		return correlationParent.getExplicitAlias();
	}

	@Override
	public void setExplicitAlias(@Nullable String explicitAlias) {
		throw new UnsupportedOperationException( "Can't set alias on a correlated root" );
	}

	@Nonnull
	@Override
	public JpaSelection<T> alias(@Nonnull String name) {
		setAlias( name );
		return this;
	}

	@Override
	public boolean isCorrelated() {
		return true;
	}

	@Override
	public SqmRoot<T> getCorrelatedRoot() {
		return this;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Set the alias on the outer parent root before creating the correlation - the correlated root inherits it via getExplicitAlias().
  2. Remove the alias() call on the correlated root; use the existing parent alias when referencing the path inside the subquery.
  3. In generic code, check root.isCorrelated() (true for SqmCorrelatedRoot) before calling alias()/setAlias().
  4. Where a distinct inner alias is required, correlate via a join or restructure the subquery select instead.

Example fix

// before - aliasing the correlated root throws
Root<Employee> correlated = subQuery.correlate(outerRoot);
correlated.alias("e2");

// after - alias the outer root first; the correlation reuses it
outerRoot.alias("e");
Root<Employee> correlated = subQuery.correlate(outerRoot);
// reference correlated.get("salary") - no extra alias needed
Defensive patterns

Strategy: type-guard

Validate before calling

// Alias the outer root BEFORE correlating; correlated roots must not be aliased
if (!outerRoot.isCorrelated()) {
    outerRoot.alias("e");
}
Root<Employee> correlated = subQuery.correlate(outerRoot); // inherits alias from parent

Type guard

static boolean aliasMutable(org.hibernate.query.criteria.JpaFrom<?, ?> from) {
    return !from.isCorrelated(); // SqmCorrelatedRoot.isCorrelated() == true and forbids setExplicitAlias
}

Try / catch

try {
    root.alias(name);
} catch (UnsupportedOperationException e) {
    // correlated root: alias lives on the correlation parent - nothing to do
}

Prevention

When it happens

Trigger: Criteria code doing Root<X> r = subquery.correlate(root); r.alias("x"); any framework that unconditionally aliases every root it touches, including correlated ones; SqmCorrelatedRoot.alias(name) calls in HQL-building helpers that mirror outer aliasing onto the correlation.

Common situations: Specification/query-builder libraries that assign generated aliases to all roots for deterministic SQL; code copied from a main query where aliasing roots is fine, reused inside an exists() subquery; upgrading Hibernate versions where alias handling of correlated roots became strict (previously ignored or tolerated).

Related errors


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