hibernate/hibernate-orm · error · IllegalArgumentException
First result cannot be negative
Error message
First result cannot be negative
What it means
SelectionQueryImpl.setFirstResult checks the session is open and then requires startPosition >= 0, throwing IllegalArgumentException for any negative value. Negative offsets have no meaning in the generated pagination SQL (offset/limit), so they are rejected outright rather than clamped.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/SelectionQueryImpl.java:423
@Override
@Nullable
public Integer getFetchSize() {
return getQueryOptions().getFetchSize();
}
@Override
@Nonnull
public SelectionQueryImplementor<R> setFetchSize(int fetchSize) {
queryOptions.setFetchSize( fetchSize );
return this;
}
@Override
@Nonnull
public SelectionQueryImplementor<R> setFirstResult(int startPosition) {
session.checkOpen();
if ( startPosition < 0 ) {
throw new IllegalArgumentException( "First result cannot be negative" );
}
queryOptions.getLimit().setFirstRow( startPosition );
return this;
}
@Override
@Nonnull
public SelectionQueryImplementor<R> setMaxResults(int maxResults) {
if ( maxResults < 0 ) {
throw new IllegalArgumentException( "Max results cannot be negative" );
}
session.checkOpen();
queryOptions.getLimit().setMaxRows( maxResults );
return this;
}
@Override
public SelectionQueryImplementor<R> setPage(Page page) {View on GitHub (pinned to fad1729dce)
Solutions
- Clamp the offset: setFirstResult(Math.max(0, offset)).
- Validate and normalize page/size at the controller boundary (page >= 1 or >= 0 consistently, size > 0).
- Do not use -1 as a sentinel for 'no offset'; use 0 or skip the call.
Example fix
// before int page = 0; // user sent page=0 in a 1-based UI q.setFirstResult((page - 1) * size); // -size -> throws // after int page = Math.max(1, requestedPage); q.setFirstResult((page - 1) * size);
Defensive patterns
Strategy: validation
Validate before calling
static int safeFirstResult(long page, int size) {
if (page < 1 || size < 1) throw new IllegalArgumentException("page >= 1 and size >= 1 required");
return (int) Math.max(0, (page - 1) * size);
} Prevention
- Normalize page/size once at the controller boundary.
- Never use -1 as a sentinel offset; default to 0 or skip setFirstResult.
- Standardize on 1-based or 0-based page indices across the whole API.
When it happens
Trigger: Calling setFirstResult(-1) directly, or more often setFirstResult((page - 1) * size) with page=0 in a 1-based UI, or a user-supplied page parameter parsed without validation (e.g. ?page=-2).
Common situations: Web pagination controllers mixing 0-based and 1-based page indices; computed offsets underflowing to negative; using -1 as an 'unset' sentinel default that leaks into the call.
Related errors
- Fetch clause may not be null
- Can't render offset and fetch clause for subquery
- Can't render offset and fetch clause for subquery
- Can't emulate fetch clause type:
- Can't emulate offset clause in subquery
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7a40069fc6218fa5.
Report an issue: GitHub.