quarkusio/quarkus · error · UnsupportedOperationException

Cannot call hasNextPage() before fetching results with list(

Error message

Cannot call hasNextPage() before fetching results with list()

What it means

With cursor-based (keyed) pagination, hasNextPage() can only be answered from the cursor of the previously fetched page. If no page has been fetched yet (list() was never called), Panache throws UnsupportedOperationException because there is no cursor to evaluate.

Source

Thrown at extensions/panache/hibernate-orm-panache-common/runtime/src/main/java/io/quarkus/hibernate/orm/panache/common/runtime/CommonPanacheQueryImpl.java:251

        } else {
            page(page.first());
        }
    }

    public void lastPage() {
        checkPagination();
        if (keyedPage != null) {
            throw new UnsupportedOperationException(
                    "Cannot navigate to last page in cursor-based pagination");
        }
        page(page.index(pageCount() - 1));
    }

    public boolean hasNextPage() {
        checkPagination();
        if (keyedPage != null) {
            if (lastKeyedResult == null) {
                throw new UnsupportedOperationException(
                        "Cannot call hasNextPage() before fetching results with list()");
            }
            return !lastKeyedResult.isLastPage();
        }
        return page.index < (pageCount() - 1);
    }

    public boolean hasPreviousPage() {
        checkPagination();
        if (keyedPage != null) {
            if (lastKeyedResult == null) {
                throw new UnsupportedOperationException(
                        "Cannot call hasPreviousPage() before fetching results with list()");
            }
            return !lastKeyedResult.isFirstPage();
        }
        return page.index > 0;
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call list() first to fetch the current page, then check hasNextPage().
  2. Use offset pagination (page(int, int)) if you need hasNextPage() before the first fetch.
  3. Restructure the loop so the existence check happens after each fetch iteration.

Example fix

// before
query.page(KeyedPage.of(KeyedPage.NEXT, 50));
if (query.hasNextPage()) { ... } // throws

// after
query.page(KeyedPage.of(KeyedPage.NEXT, 50));
List<MyEntity> page = query.list();
while (!page.isEmpty()) {
    // process page
    if (!query.hasNextPage()) break;
    page = query.nextPage().list();
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure a fetch happened before checking
if (lastFetchedPage == null) {
    query.list(); // fetch current page first
}
boolean hasNext = query.hasNextPage();

Try / catch

try {
    return query.hasNextPage();
} catch (UnsupportedOperationException e) {
    query.list();
    return query.hasNextPage();
}

Prevention

When it happens

Trigger: Calling hasNextPage() on a query paginated with KeyedPage before calling list()/stream() at least once.

Common situations: Checking whether a next page exists immediately after building the query, before fetching; or refactoring offset-pagination code where hasNextPage() works pre-fetch since it uses pageCount().

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/fb3dcf14391bc1f0. Report an issue: GitHub.