hibernate/hibernate-orm · error · IllegalArgumentException

Fetch clause may not be null

Error message

Fetch clause may not be null

What it means

QueryPart.setFetchClauseExpression(Expression, FetchClauseType) backs HQL/JPQL 'fetch first/next' clauses. Passing a non-null expression together with a null FetchClauseType is contradictory - the AST cannot represent 'fetch N' without knowing whether it is ROWS_ONLY, ROWS_WITH_TIES, PERCENT_ONLY or PERCENT_WITH_TIES - so an IllegalArgumentException is thrown. Passing a null expression is the supported way to clear the clause and resets both fields.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/tree/select/QueryPart.java:113

		return offsetClauseExpression;
	}

	public void setOffsetClauseExpression(Expression offsetClauseExpression) {
		this.offsetClauseExpression = offsetClauseExpression;
	}

	public Expression getFetchClauseExpression() {
		return fetchClauseExpression;
	}

	public void setFetchClauseExpression(Expression fetchClauseExpression, FetchClauseType fetchClauseType) {
		if ( fetchClauseExpression == null ) {
			this.fetchClauseExpression = null;
			this.fetchClauseType = FetchClauseType.ROWS_ONLY;
		}
		else {
			if ( fetchClauseType == null ) {
				throw new IllegalArgumentException( "Fetch clause may not be null" );
			}
			this.fetchClauseExpression = fetchClauseExpression;
			this.fetchClauseType = fetchClauseType;
		}
	}

	public FetchClauseType getFetchClauseType() {
		return fetchClauseType;
	}

}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Pass a concrete FetchClauseType (usually FetchClauseType.ROWS_ONLY) whenever the expression is non-null
  2. To clear the fetch clause call setFetchClauseExpression(null, null) - the null branch resets both fields
  3. Validate arguments up front: only (null, ...) or (expr, non-null type) are legal combinations

Example fix

// before
queryPart.setFetchClauseExpression( rowCount, null ); // throws

// after
queryPart.setFetchClauseExpression( rowCount, FetchClauseType.ROWS_ONLY );
Defensive patterns

Strategy: validation

Validate before calling

void applyFetchClause(QueryPart part, Expression expr, FetchClauseType type) {
    if ( expr == null ) {
        part.setFetchClauseExpression( null, null );
    } else {
        Objects.requireNonNull( type, "FetchClauseType required for non-null expression" );
        part.setFetchClauseExpression( expr, type );
    }
}

Prevention

When it happens

Trigger: Programmatic construction of a QueryPart (custom translators, criteria-to-SQL AST code) calling setFetchClauseExpression(expr, null); copy/clone routines that copy the expression but not the type; misuse of the setter with a non-null expression and missing type.

Common situations: Custom SqmTranslator/SqlAstCreation extensions building pagination; porting code between Hibernate versions where the setter signature changed; dialect-specific fetch-clause emulation setting the expression programmatically.

Related errors


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