{"record":{"id":"fb3dcf14391bc1f0","repo":"quarkusio/quarkus","slug":"cannot-call-hasnextpage-before-fetching-results","errorCode":null,"errorMessage":"Cannot call hasNextPage() before fetching results with list()","messagePattern":"Cannot call hasNextPage\\(\\) before fetching results with list\\(\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"extensions/panache/hibernate-orm-panache-common/runtime/src/main/java/io/quarkus/hibernate/orm/panache/common/runtime/CommonPanacheQueryImpl.java","lineNumber":251,"sourceCode":"        } else {\n            page(page.first());\n        }\n    }\n\n    public void lastPage() {\n        checkPagination();\n        if (keyedPage != null) {\n            throw new UnsupportedOperationException(\n                    \"Cannot navigate to last page in cursor-based pagination\");\n        }\n        page(page.index(pageCount() - 1));\n    }\n\n    public boolean hasNextPage() {\n        checkPagination();\n        if (keyedPage != null) {\n            if (lastKeyedResult == null) {\n                throw new UnsupportedOperationException(\n                        \"Cannot call hasNextPage() before fetching results with list()\");\n            }\n            return !lastKeyedResult.isLastPage();\n        }\n        return page.index < (pageCount() - 1);\n    }\n\n    public boolean hasPreviousPage() {\n        checkPagination();\n        if (keyedPage != null) {\n            if (lastKeyedResult == null) {\n                throw new UnsupportedOperationException(\n                        \"Cannot call hasPreviousPage() before fetching results with list()\");\n            }\n            return !lastKeyedResult.isFirstPage();\n        }\n        return page.index > 0;\n    }","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/panache/hibernate-orm-panache-common/runtime/src/main/java/io/quarkus/hibernate/orm/panache/common/runtime/CommonPanacheQueryImpl.java#L233-L269","documentation":"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.","triggerScenarios":"Calling hasNextPage() on a query paginated with KeyedPage before calling list()/stream() at least once.","commonSituations":"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().","solutions":["Call list() first to fetch the current page, then check hasNextPage().","Use offset pagination (page(int, int)) if you need hasNextPage() before the first fetch.","Restructure the loop so the existence check happens after each fetch iteration."],"exampleFix":"// before\nquery.page(KeyedPage.of(KeyedPage.NEXT, 50));\nif (query.hasNextPage()) { ... } // throws\n\n// after\nquery.page(KeyedPage.of(KeyedPage.NEXT, 50));\nList<MyEntity> page = query.list();\nwhile (!page.isEmpty()) {\n    // process page\n    if (!query.hasNextPage()) break;\n    page = query.nextPage().list();\n}","handlingStrategy":"validation","validationCode":"// ensure a fetch happened before checking\nif (lastFetchedPage == null) {\n    query.list(); // fetch current page first\n}\nboolean hasNext = query.hasNextPage();","typeGuard":null,"tryCatchPattern":"try {\n    return query.hasNextPage();\n} catch (UnsupportedOperationException e) {\n    query.list();\n    return query.hasNextPage();\n}","preventionTips":["With keyed pagination always fetch (list()) before querying page existence.","Wrap keyed pagination in an iterator-like helper that fetches before peeking.","Use offset pagination when pre-fetch checks are required."],"tags":["panache","pagination","cursor","call-order"],"backgroundTag":"cursor-pagination-fetch-before-inspect","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}