quarkusio/quarkus · error · UnsupportedOperationException

Cursor-based pagination is not supported by Hibernate Reacti

Error message

Cursor-based pagination is not supported by Hibernate Reactive

What it means

PanacheManagedReactiveQueryImpl.cursor(pageIndex, pageSize) — offset/size based cursor pagination — is not implemented for the Hibernate Reactive backing, which only offers page(pageIndex, pageSize) plus nextPage() iteration. Calling cursor throws UnsupportedOperationException unconditionally.

Source

Thrown at extensions/data/hibernate/runtime/src/main/java/io/quarkus/data/hibernate/runtime/hr/PanacheManagedReactiveQueryImpl.java:93

            return PageRequest.ofPage(page.index + 1, page.size, false);
        }

        @Override
        public ReactiveDataQuery<Entity> request(PageRequest request) {
            // FIXME: let's hope they fix their page indices to 0-based
            delegate.page((int) (request.page() - 1), request.size());
            return PanacheManagedReactiveQueryImpl.this;
        }

        @Override
        public ReactiveDataQuery<Entity> page(long pageIndex, int pageSize) {
            delegate.page((int) pageIndex, pageSize);
            return PanacheManagedReactiveQueryImpl.this;
        }

        @Override
        public ReactiveDataQuery<Entity> cursor(long pageIndex, int pageSize) {
            throw new UnsupportedOperationException("Cursor-based pagination is not supported by Hibernate Reactive");
        }

        @Override
        public ReactiveDataQuery<Entity> next() {
            delegate.nextPage();
            return PanacheManagedReactiveQueryImpl.this;
        }

        @Override
        public ReactiveDataQuery<Entity> previous() {
            delegate.previousPage();
            return PanacheManagedReactiveQueryImpl.this;
        }

        @Override
        public ReactiveDataQuery<Entity> first() {
            delegate.firstPage();
            return PanacheManagedReactiveQueryImpl.this;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Use page(pageIndex, pageSize) instead, and navigate with next()/nextPage() for subsequent pages
  2. Compute the absolute page number yourself and pass it to page()
  3. If true cursor/keyset pagination is needed, use an explicit order-by + where id > :lastId query

Example fix

// before
query.cursor(pageIndex, pageSize).list();
// after
query.page(pageIndex, pageSize).list(); // subsequent pages: query.nextPage().list()
Defensive patterns

Strategy: fallback

Validate before calling

// no pre-check possible; cursor() always throws — avoid calling it on reactive queries

Type guard

boolean supportsCursorPagination(Object q) { return !(q instanceof PanacheManagedReactiveQueryImpl); }

Try / catch

try { q.cursor(idx, size); } catch (UnsupportedOperationException e) { q.page(idx, size); }

Prevention

When it happens

Trigger: Calling cursor(pageIndex, pageSize) on a reactive managed Panache query, typically to combine an explicit offset with paging.

Common situations: Code ported from the blocking Panache query API that uses cursor(); frameworks or helpers that map keyset/offset pagination to cursor(pageIndex, pageSize).

Related errors


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