hibernate/hibernate-orm · error · IllegalArgumentException
Selection item in a multi-select cannot contain compound tup
Error message
Selection item in a multi-select cannot contain compound tuple-valued elements
What it means
Twin rule of the array variant: multiselect items must not be compound selections whose Java type is Tuple (produced by cb.tuple(...)). The JPA contract forbids tuple- or array-valued compound items as arguments to multiselect because the final row composition is governed by the multiselect call itself, so Hibernate's checkMultiselect rejects them immediately.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java:1339
* @param selections The selection varargs to check
*
* @throws IllegalArgumentException If the selection items are not valid per
* according to {@linkplain CriteriaQuery#multiselect this documentation}.
* <i>"An argument to the multiselect method must not be a tuple-
* or array-valued compound selection item."</i>
*/
private void checkMultiselect(List<? extends Selection<?>> selections) {
final HashSet<String> aliases = new HashSet<>( determineProperSizing( selections.size() ) );
for ( var selection : selections ) {
if ( selection.isCompoundSelection() ) {
final Class<?> javaType = selection.getJavaType();
if ( javaType.isArray() ) {
throw new IllegalArgumentException(
"Selection item in a multi-select cannot contain compound array-valued elements"
);
}
if ( Tuple.class.isAssignableFrom( javaType ) ) {
throw new IllegalArgumentException(
"Selection item in a multi-select cannot contain compound tuple-valued elements"
);
}
}
final String alias = selection.getAlias();
if ( StringHelper.isNotEmpty( alias ) && !aliases.add( alias ) ) {
throw new IllegalArgumentException( "Multi-select expressions have duplicate alias '" + alias + "'" );
}
}
}
@Nonnull
@Override
public <N extends Number> SqmExpression<Double> avg(@Nonnull Expression<N> argument) {
return getFunctionDescriptor( "avg" ).generateSqmExpression(
(SqmTypedNode<?>) argument,
null,
queryEngineView on GitHub (pinned to fad1729dce)
Solutions
- Spread the tuple's arguments into multiselect: multiselect(root.get("a"), root.get("b"), root.get("c")).
- Or keep tuple() as the sole top-level selection: query.select(cb.tuple(a, b, c)).
- Audit helper methods that return Selection<Tuple>/Selection<Object[]> and stop feeding them to multiselect.
Example fix
// before
query.multiselect(cb.tuple(root.get("sku"), root.get("name")), root.get("qty"));
// -> Selection item in a multi-select cannot contain compound tuple-valued elements
// after
query.multiselect(root.get("sku"), root.get("name"), root.get("qty")); Defensive patterns
Strategy: validation
Validate before calling
boolean hasNestedTupleItem(List<? extends Selection<?>> items) {
for (Selection<?> s : items) {
if (s.isCompoundSelection() && Tuple.class.isAssignableFrom(s.getJavaType())) return true;
}
return false;
}
if (hasNestedTupleItem(selections)) throw new IllegalArgumentException("flatten tuple() items before multiselect"); Type guard
static boolean isCompoundTupleItem(Selection<?> s) {
return s.isCompoundSelection() && Tuple.class.isAssignableFrom(s.getJavaType());
} Try / catch
try {
query.multiselect(items);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("tuple-valued")) { /* spread cb.tuple(...) args into multiselect */ }
else throw e;
} Prevention
- Spread tuple components into multiselect; keep tuple() only as the single top-level selection.
- When migrating query.select(cb.tuple(...)) code to multiselect, delete the tuple wrapper.
- Check helper methods returning Selection<Tuple> before feeding them to multiselect.
When it happens
Trigger: query.multiselect(cb.tuple(root.get("a"), root.get("b")), root.get("c")); reusing a helper that returns Selection<Tuple> as one argument of multiselect; migrating a Tuple query into multiselect without unwrapping the tuple(...) wrapper.
Common situations: Dynamic report projections assembled from per-column helper methods where one helper already groups columns into a tuple; refactors from query.select(cb.tuple(...)) to multiselect(...).
Related errors
- Selection item in a multi-select cannot contain compound arr
- Unable to unwrap to {}
- Multi-select expressions have duplicate alias '{}'
- Tuple constructor must have at least one element
- Informix does not support binary literals
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/6d569082300069cd.
Report an issue: GitHub.