hibernate/hibernate-orm · error · IllegalStateException

The JPA specification does not support subqueries having a f

Error message

The JPA specification does not support subqueries having a fetch or offset clause. Please disable the JPA query compliance if you want to use this feature.

What it means

JPA criteria subqueries support neither OFFSET nor FETCH/LIMIT clauses, so with hibernate.jpa.compliance.query=true Hibernate rejects them: JpaSubQuery.setOffset(...)/offset(...) and setFetch(...)/fetch(...) call validateComplianceFetchOffset(), which throws IllegalStateException for both paging operations. This is one of three compliance guards on subqueries (multiselect, orderBy, fetch/offset).

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/select/SqmSubQuery.java:509

	private void validateComplianceMultiselect() {
		if ( nodeBuilder().isJpaQueryComplianceEnabled() ) {
			throw new IllegalStateException(
					"The JPA specification does not support subqueries having multiple select items. " +
							"Please disable the JPA query compliance if you want to use this feature." );
		}
	}

	private void validateComplianceOrderBy() {
		if ( nodeBuilder().isJpaQueryComplianceEnabled() ) {
			throw new IllegalStateException(
					"The JPA specification does not support subqueries having an order by clause. " +
							"Please disable the JPA query compliance if you want to use this feature." );
		}
	}

	private void validateComplianceFetchOffset() {
		if ( nodeBuilder().isJpaQueryComplianceEnabled() ) {
			throw new IllegalStateException(
					"The JPA specification does not support subqueries having a fetch or offset clause. " +
							"Please disable the JPA query compliance if you want to use this feature." );
		}
	}

	@Nonnull
	@Override
	public <Y> SqmRoot<Y> correlate(@Nonnull Root<Y> parentRoot) {
		final SqmCorrelatedRoot<Y> correlated = ( (SqmRoot<Y>) parentRoot ).createCorrelation();
		getQuerySpec().addRoot( correlated );
		return correlated;
	}

	@Nonnull
	@Override
	public <X, Y> SqmFrom<X, Y> correlate(@Nonnull From<X, Y> parentFrom) {
		if ( parentFrom instanceof Root<?> ) {
			//noinspection unchecked

View on GitHub (pinned to fad1729dce)

Solutions

  1. Move the limit out of the subquery into the outer query's setFirstResult/setMaxResults, if semantics allow
  2. Disable the guard for these queries: hibernate.jpa.compliance.query=false (JPA simply has no compliant way to limit a subquery)
  3. Rewrite the limited subquery as a CTE (with(...)) or a ROW_NUMBER() window-function join, which keeps the outer query compliant

Example fix

// before (hibernate.jpa.compliance.query=true)
sub.orderBy(cb.desc(subRoot.get("score")));
sub.setFetch(1); // IllegalStateException

// after — top-N via window function in outer query, no subquery limit
Expression<Long> rn = cb.function("row_number", Long.class);
// ... filter on rn <= n in the outer query, or set hibernate.jpa.compliance.query=false
Defensive patterns

Strategy: validation

Validate before calling

boolean compliance = ((SqmCriteriaNodeBuilder) cb).isJpaQueryComplianceEnabled();
if (!compliance) { sub.setFetch(limit); } else { /* use outer-query setMaxResults or a CTE rewrite */ }

Try / catch

try { sub.setFetch(n); } catch (IllegalStateException e) { if (e.getMessage().contains("fetch or offset")) { emQuery.setMaxResults(n); } else throw e; }

Prevention

When it happens

Trigger: hibernate.jpa.compliance.query=true plus subquery.setOffset(n)/setFetch(n) (or the JpaSubQuery#offset/#fetch variants) — typically pagination or top-N patterns pushed inside a subquery.

Common situations: Top-N-per-group queries (order + limit inside subquery) executed under a compliance-enabled configuration; migrating paginated native queries to criteria while a platform team enforces JPA compliance properties.

Related errors


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