apache/seatunnel · error · IllegalArgumentException

Page number exceeds total pages

Error message

Page number exceeds total pages

What it means

PageBaseServlet.writeJsonWithPagination rejects a page whose computed start offset exceeds the total number of records with 'Page number exceeds total pages'. This happens when start=(page-1)*rows > total, i.e. the requested page lies past the last page of data.

Source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/servlet/PageBaseServlet.java:57

            HttpServletRequest req, HttpServletResponse resp, JsonArray jsonArray)
            throws IOException {
        int total = jsonArray.size();

        // fetch pagination params, if page exist, then paginate data,pagination data format like:
        // {"data": [], "total": 10}
        Map<String, String> parameterMap = getParameterMap(req);
        if (parameterMap != null && parameterMap.containsKey(pageParam)) {
            int page = Integer.parseInt(parameterMap.get(pageParam));
            int rows =
                    parameterMap.get(rowsParam) != null
                            ? Integer.parseInt(parameterMap.get(rowsParam))
                            : 10;
            int start = (page - 1) * rows;
            if (start > total || page < 1) {
                throw new IllegalArgumentException(
                        page < 1
                                ? "Page number must be greater than 0"
                                : "Page number exceeds total pages");
            }
            JsonArray paginatedArray = new JsonArray();
            jsonArray
                    .values()
                    .subList(start, Math.min(start + rows, total))
                    .forEach(
                            t -> {
                                paginatedArray.add(t);
                            });
            JsonObject paginatedObj = new JsonObject();
            paginatedObj.add("data", paginatedArray);
            paginatedObj.add("total", total);
            writeJson(resp, paginatedObj);
        } else {
            writeJson(resp, jsonArray);
        }
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Request a page within range; compute lastPage = max(1, ceil(total/rows)) client-side
  2. When a filter reduces the result set, reset pagination to page 1
  3. Handle the error by clamping to the last page and retrying
  4. Return 400 with total page count in the body so clients can self-correct

Example fix

// before
// results shrank from 300 to 120 rows, still fetching page 30
fetch(`/finished-jobs?page=30&rows=10`);
// after
const lastPage = Math.max(1, Math.ceil(total / rows));
fetch(`/finished-jobs?page=${Math.min(page, lastPage)}&rows=10`);
Defensive patterns

Strategy: validation

Validate before calling

int lastPage = Math.max(1, (int) Math.ceil((double) total / rows));
int safePage = Math.min(page, lastPage);

Type guard

boolean isWithinRange(int page, int total, int rows) { return page >= 1 && (page - 1) * rows < total; }

Try / catch

try { fetchPage(page); } catch (IllegalArgumentException e) { fetchPage(Math.max(1, page - 1)); } // walk back when data shrank

Prevention

When it happens

Trigger: GET a paginated endpoint with a page number beyond the available rows, e.g. 200 total rows with rows=10 and page=21+; also triggered when the result set shrinks (filters/new data) between requests and the client retries the old page.

Common situations: Deep pagination after data deletion or job retention cleanup; saved UI links to a high page number; stale 'next page' links after the list shrank; large page values typed by users or tests.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/2b5485b02e3eb9ad. Report an issue: GitHub.