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
- Request a page within range; compute lastPage = max(1, ceil(total/rows)) client-side
- When a filter reduces the result set, reset pagination to page 1
- Handle the error by clamping to the last page and retrying
- 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
- Reset to page 1 whenever filters change
- Refresh total counts before deep pagination
- Cap UI pagination controls at the last page
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
- Page number must be greater than 0
- Parameter 'pluginName' cannot be empty.
- The jobId must not be empty.
- The jobId must not be empty.
- The jobId must not be empty.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/2b5485b02e3eb9ad.
Report an issue: GitHub.