hibernate/hibernate-orm · error · IllegalStateException

Multiple from elements expose unqualified attribute: ${ident

Error message

Multiple from elements expose unqualified attribute: ${identifierText}

What it means

Thrown while resolving an unqualified identifier in group-by/order-by against the select list: the identifier names a sub-path source exposed by a select item that is an SqmFrom, and a second from-element select item exposes the same attribute name. The first match records sqmPosition; the second match finds sqmPosition != 0 and throws IllegalStateException because the positional reference would be ambiguous.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java:1666

				// If the current query part is a query group, check if the text matches
				// an attribute name of one of the selected SqmFrom elements or the path source name of a SqmPath
				SqmFrom<?, ?> found = null;
				int sqmPosition = 0;
				final var selections = queryPart.getFirstQuerySpec().getSelectClause().getSelections();
				for ( int i = 0; i < selections.size(); i++ ) {
					final var sqmSelection = selections.get( i );
					if ( identifierText.equals( sqmSelection.getAlias() ) ) {
						return new SqmAliasedNodeRef(
								i + 1,
								nodeBuilder.getIntegerType(),
								nodeBuilder
						);
					}
					final var selectableNode = sqmSelection.getSelectableNode();
					if ( selectableNode instanceof SqmFrom<?, ?> fromElement ) {
						if ( fromElement.getReferencedPathSource().findSubPathSource( identifierText ) != null ) {
							if ( sqmPosition != 0 ) {
								throw new IllegalStateException(
										"Multiple from elements expose unqualified attribute: " + identifierText );
							}
							found = fromElement;
							sqmPosition = i + 1;
						}
					}
					else if ( selectableNode instanceof SqmPath<?> path ) {
						if ( identifierText.equals( path.getReferencedPathSource().getPathName() ) ) {
							if ( sqmPosition != 0 ) {
								throw new IllegalStateException(
										"Multiple from elements expose unqualified attribute: " + identifierText );
							}
							sqmPosition = i + 1;
						}
					}
				}
				if ( found != null ) {
					return new SqmAliasedNodeRef(

View on GitHub (pinned to fad1729dce)

Solutions

  1. Qualify the identifier with the from-alias: 'group by e.name'
  2. Give the select expression an alias and group by that alias
  3. Restructure the select list so only one candidate from-element exposes the attribute

Example fix

// before
select e, d from Employee e join e.department d group by name

// after
select e, d from Employee e join e.department d group by e.name
Defensive patterns

Strategy: validation

Validate before calling

static boolean uniqueAttributeExposure(EntityManagerFactory emf, String hqlEntity, String attr, List<String> otherAliases) {
    // conservative check: ensure the unqualified attribute exists on exactly one from-element type
    var metamodel = emf.getMetamodel();
    long matches = otherAliases.stream().filter(a -> {
        try {
            var attrFound = metamodel.entity(a).getAttribute(attr) != null;
            return attrFound;
        } catch (IllegalArgumentException unknown) {
            return false;
        }
    }).count();
    return matches <= 1;
}

Try / catch

try {
    return session.createQuery(hql, Object[].class).list();
} catch (IllegalStateException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Multiple from elements expose unqualified attribute")) {
        throw new IllegalArgumentException("Ambiguous group-by attribute - qualify it with an alias: " + hql, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: 'select e, d from Employee e join Department d ... group by name' where both e and d expose an attribute 'name'; any unqualified group-by identifier resolvable through two or more from-elements appearing in the select list.

Common situations: Entities sharing attribute names (id, name, version, code); queries selecting multiple roots or joins and grouping by a bare column name; refactors that add a second from-element with a colliding attribute name.

Related errors


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