hibernate/hibernate-orm · error · IllegalStateException

Unsupported tuple comparison combination. LHS is neither a t

Error message

Unsupported tuple comparison combination. LHS is neither a tuple nor a tuple subquery but RHS is a tuple: 

What it means

While flattening a ComparisonPredicate whose right-hand side is a SqlTuple, the translator accepts only a tuple or tuple subquery on the left-hand side. If the RHS is a tuple but the LHS is neither, the AST combination is considered impossible/unsupported and this IllegalStateException (dumping the predicate) is thrown - typically indicating a malformed or unusual query model rather than a supported feature gap.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java:8630

							lhsExpression,
							comparisonPredicate.getOperator(),
							comparisonPredicate.getRightHandExpression()
					);
				}
				else {
					emulateSubQueryRelationalRestrictionPredicate(
							comparisonPredicate,
							false,
							(SelectStatement) lhsExpression,
							rhsTuple,
							this::renderSelectTupleComparison,
							// Since we switch the order of operands, we have to invert the operator
							comparisonPredicate.getOperator().invert()
					);
				}
			}
			else {
				throw new IllegalStateException(
						"Unsupported tuple comparison combination. LHS is neither a tuple nor a tuple subquery but RHS is a tuple: " + comparisonPredicate );
			}
		}
		else {
			renderComparison(
					comparisonPredicate.getLeftHandExpression(),
					comparisonPredicate.getOperator(),
					comparisonPredicate.getRightHandExpression()
			);
		}
	}

	private boolean needsTupleComparisonEmulation(ComparisonOperator operator) {
		if ( !dialect.supportsRowValueConstructorSyntax() ) {
			return true;
		}
		return switch (operator) {
			case LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL ->

View on GitHub (pinned to fad1729dce)

Solutions

  1. Rewrite the comparison to compare matching shapes (tuple vs tuple, scalar vs scalar)
  2. Compare component-wise: a = :a and b = :b instead of tuple syntax
  3. Upgrade to the latest Hibernate 6.x - report the query to HHH if it reproduces, since this signals an internal inconsistency

Example fix

// before
... where (e.embeddedA, e.embeddedB) = :scalarParam // tuple vs non-tuple

// after
... where e.embeddedA = :a and e.embeddedB = :b
Defensive patterns

Strategy: try-catch

Validate before calling

// When building comparisons programmatically, keep both sides shape-compatible
boolean lhsTuple = lhs instanceof SqlTuple || lhs instanceof SelectStatement;
boolean rhsTuple = rhs instanceof SqlTuple;
if (rhsTuple && !lhsTuple) { /* force lhs to a tuple or rhs to scalar before adding the predicate */ }

Try / catch

try {
    query.list();
} catch (IllegalStateException e) {
    if (String.valueOf(e.getMessage()).startsWith("Unsupported tuple comparison combination")) {
        // log the predicate, rewrite as component-wise comparisons; report to HHH with the query
    } else throw e;
}

Prevention

When it happens

Trigger: A query model where a SqlTuple ends up on one side of a comparison while the other side is a plain scalar expression - usually produced by dialect-specific comparison flattening, criteria misuse, or SQM rewriting - rather than by plain HQL.

Common situations: Hibernate internal invariant hit via complex id-class/embeddable comparisons on specific dialects; custom SqmTranslator/SQM function descriptors emitting tuples into comparisons; rare HHH bugs fixed across 6.x versions.

Related errors


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