hibernate/hibernate-orm · error · SemanticException
Tuple constructor must have at least one element
Error message
Tuple constructor must have at least one element
What it means
SqmTuple groups several expressions into one tuple-typed expression (used by in-tuples, multiselect, compound selections). A tuple with zero expressions has no component types to resolve (resolveTupleType) and cannot be rendered, so the constructor throws SemanticException('Tuple constructor must have at least one element').
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmTuple.java:54
implements JpaCompoundSelection<T> {
private final List<SqmExpression<?>> groupedExpressions;
public SqmTuple(NodeBuilder nodeBuilder, SqmExpression<?>... groupedExpressions) {
this( Arrays.asList( groupedExpressions ), nodeBuilder );
}
public SqmTuple(NodeBuilder nodeBuilder, SqmBindableType<T> type, SqmExpression<?>... groupedExpressions) {
this( Arrays.asList( groupedExpressions ), type, nodeBuilder );
}
public SqmTuple(List<SqmExpression<?>> groupedExpressions, NodeBuilder nodeBuilder) {
this( groupedExpressions, null, nodeBuilder );
}
public SqmTuple(List<SqmExpression<?>> groupedExpressions, @Nullable SqmBindableType<T> type, NodeBuilder nodeBuilder) {
super( type, nodeBuilder );
if ( groupedExpressions.isEmpty() ) {
throw new SemanticException( "Tuple constructor must have at least one element" );
}
this.groupedExpressions = groupedExpressions;
if ( type == null ) {
setExpressibleType( nodeBuilder.getTypeConfiguration().resolveTupleType( groupedExpressions ) );
}
}
@Override
public SqmTuple<T> copy(SqmCopyContext context) {
final var existing = context.getCopy( this );
if ( existing != null ) {
return existing;
}
final List<SqmExpression<?>> groupedExpressions = new ArrayList<>( this.groupedExpressions.size() );
for ( SqmExpression<?> groupedExpression : this.groupedExpressions ) {
groupedExpressions.add( groupedExpression.copy( context ) );
}
final SqmTuple<T> expression = context.registerCopy(View on GitHub (pinned to fad1729dce)
Solutions
- Guard the empty case: skip the query, return early, or substitute a default selection (e.g. the root id or a literal).
- For dynamic IN lists, check emptiness before building the predicate and choose explicit semantics (match-nothing vs. skip filter).
- Validate at the API boundary that callers supply at least one selection.
Example fix
// before
List<Selection<?>> sels = buildSelections( filter ); // may be empty
cq.multiselect( sels ); // SemanticException
// after
if ( sels.isEmpty() ) {
cq.multiselect( root.get( "id" ) ); // or throw a meaningful domain exception
} else {
cq.multiselect( sels );
} Defensive patterns
Strategy: validation
Validate before calling
if ( selections == null || selections.isEmpty() ) {
throw new IllegalArgumentException( "multiselect/tuple requires at least one selection" );
}
cq.multiselect( selections ); Prevention
- Check selection lists for emptiness before calling multiselect()/tuple().
- For dynamic IN lists, decide explicit empty-list semantics (skip filter vs. match nothing) up front.
- Validate at the API boundary that callers supply at least one selection.
When it happens
Trigger: Creating an SqmTuple or builder.tuple with an empty list: cq.multiselect(new ArrayList<>()), builder.tuple(Collections.emptyList()), or building an IN-tuple predicate from a dynamically generated list of value combinations that turned out empty.
Common situations: Dynamic query construction where selections or IN values come from user input, configuration, or a loop that can yield zero items; empty multiselect lists after filtering; criteria helpers that wrap arbitrary lists in tuples.
Related errors
- MappedSuperclassType cannot be used to create an SqmPath - t
- LHS cannot be null for a sub-navigable reference - {}
- Selection item in a multi-select cannot contain compound tup
- Not correlated
- Could not interpret attribute '%s' of basic-valued path '%s'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/5a589c160cdbde6e.
Report an issue: GitHub.