hibernate/hibernate-orm · error · IllegalArgumentException
Can't emulate offset clause in subquery
Error message
Can't emulate offset clause in subquery
What it means
IngresSqlAstTranslator.visitOffsetFetchClause() can only render native OFFSET/FETCH when the database version supports it (supportsOffsetFetchClause()). When it does not, and the offset appears in a non-root QueryPart (a subquery), there is no emulation available on Ingres, so it throws IllegalArgumentException.
Source
Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java:84
}
@Override
protected void renderOffsetExpression(Expression offsetExpression) {
if ( supportsParameterOffsetFetchExpression() ) {
super.renderOffsetExpression( offsetExpression );
}
else {
renderExpressionAsLiteral( offsetExpression, getJdbcParameterBindings() );
}
}
@Override
public void visitOffsetFetchClause(QueryPart queryPart) {
if ( supportsOffsetFetchClause() ) {
renderOffsetFetchClause( queryPart, false );
}
else if ( !queryPart.isRoot() && queryPart.getOffsetClauseExpression() != null ) {
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
}
}
@Override
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
renderComparisonEmulateIntersect( lhs, operator, rhs );
}
@Override
protected void renderSelectTupleComparison(
List<SqlSelection> lhsExpressions,
SqlTuple tuple,
ComparisonOperator operator) {
emulateSelectTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
}
@Override
protected void renderPartitionItem(Expression expression) {View on GitHub (pinned to fad1729dce)
Solutions
- Move pagination to the top-level query so only the outer query carries an offset
- Replace the offset subquery with keyset-style predicates (where orderedColumn > :cursor)
- Run the statement as native SQL with a formulation the Ingres server accepts
Example fix
// before select e from Event e where e.sourceId in (select s.id from Source s order by s.lastSeen offset 20 rows fetch next 10 rows only) // after - keyset instead of offset inside the subquery select e from Event e where e.sourceId in (select s.id from Source s where s.lastSeen < :cursor order by s.lastSeen desc)
Defensive patterns
Strategy: validation
Validate before calling
static boolean hasSubqueryOffset(String hql) {
return hql.toLowerCase().matches("(?s).*\\(\\s*select[^\u0000]*?(offset|fetch first)\\s.*");
}
Dialect d = session.getJdbcServices().getDialect();
if ( d instanceof IngresDialect && hasSubqueryOffset(hql) ) {
// Ingres (pre-OFFSET/FETCH) cannot paginate inside subqueries - rewrite as keyset
} Type guard
static boolean isIngres(Dialect d) { return d instanceof IngresDialect; } Try / catch
try {
return session.createQuery(hql, Event.class).getResultList();
} catch (IllegalArgumentException e) {
if ( String.valueOf(e.getMessage()).contains("offset clause in subquery") ) {
// rewrite subquery with keyset predicates and retry
}
throw e;
} Prevention
- Keep pagination at the top level of every portable query
- Prefer keyset predicates over OFFSET inside subqueries
- Test query catalogs on the oldest supported server version of each database
When it happens
Trigger: An HQL query with a subquery that declares its own offset (e.g., 'where x.id in (select y.id from Y y order by y.t offset 10)') executed on Ingres versions without native OFFSET/FETCH support — the translator must emulate the top-level offset but cannot emulate one inside a subquery.
Common situations: Porting pagination-in-subquery idioms from other databases to Ingres; legacy Ingres installations pinned to old server versions; shared query libraries that embed limited subqueries.
Related errors
- Can't emulate offset clause in subquery
- Can't emulate offset clause in subquery
- Can't emulate offset clause in subquery
- Can't emulate offset clause in subquery
- Can't emulate offset clause in subquery
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7cd9230f92cf3433.
Report an issue: GitHub.