{"record":{"id":"6a642396adb9dd97","repo":"quarkusio/quarkus","slug":"start-index-must-be-0","errorCode":null,"errorMessage":"Start index must be >= 0: ","messagePattern":"Start index must be >= 0: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/panache/panache-common/runtime/src/main/java/io/quarkus/panache/common/Range.java","lineNumber":31,"sourceCode":" * Range range = Range.of(0, 5);\n * </pre></code>\n *\n * Note that due to the end index being inclusive, it's impossible to write empty ranges.\n */\npublic class Range {\n    // FIXME: bump to long? Jakarta Data uses longs for its Limit type\n    private final int startIndex;\n    private final int lastIndex;\n\n    /**\n     * Creates a new range\n     *\n     * @param startIndex the start index to include, 0-based\n     * @param lastIndex the end index to include, 0-based\n     */\n    public Range(int startIndex, int lastIndex) {\n        if (startIndex < 0)\n            throw new IllegalArgumentException(\"Start index must be >= 0: \" + startIndex);\n        if (lastIndex < 0)\n            throw new IllegalArgumentException(\"Last index must be >= 0: \" + lastIndex);\n        if (lastIndex < startIndex)\n            throw new IllegalArgumentException(\n                    \"Last index must be >= start index: \" + lastIndex + \" is not larger or equal to \" + startIndex);\n        this.startIndex = startIndex;\n        this.lastIndex = lastIndex;\n    }\n\n    /**\n     * Creates a new range\n     *\n     * @param startIndex the start index to include, 0-based\n     * @param lastIndex the end index to include, 0-based\n     */\n    public static Range of(int startIndex, int lastIndex) {\n        return new Range(startIndex, lastIndex);\n    }","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/panache/panache-common/runtime/src/main/java/io/quarkus/panache/common/Range.java#L13-L49","documentation":"Range models an inclusive index window for queries (e.g. Range.of(start, end)). The constructor requires the start index to be non-negative; a negative start would produce an invalid query range, so it throws IllegalArgumentException.","triggerScenarios":"Calling new Range(-1, 10) or Range.of with a negative start, typically from unvalidated offsets, page math like (page-1)*size with page=0, or client input.","commonSituations":"Computing start from offset arithmetic that underflows; passing a negative \"from\" parameter from REST input; converting a 1-based page number to 0-based index incorrectly.","solutions":["Validate and clamp: Math.max(0, startIndex) before constructing the Range.","Return a 400 response for negative range input.","Prefer Page APIs (page(pageIndex, size)) and let Page validation surface clearer errors."],"exampleFix":"// before\nRange r = Range.of((page - 1) * size, page * size - 1); // page=0 -> -size\n// after\nint start = Math.max(0, (page - 1) * size);\nRange r = Range.of(start, Math.max(start, page * size - 1));","handlingStrategy":"validation","validationCode":"int start = /* computed */;\nif (start < 0) throw new BadRequestException(\"startIndex must be >= 0\");\nRange r = Range.of(start, last);","typeGuard":"Range safeRange(int start, int last) {\n    int s = Math.max(0, start);\n    return Range.of(s, Math.max(s, last));\n}","tryCatchPattern":"try {\n    Range r = Range.of(start, last);\n} catch (IllegalArgumentException e) {\n    throw new BadRequestException(\"Invalid range: \" + e.getMessage());\n}","preventionTips":["Clamp start indexes to >= 0 before Range construction","Avoid manual (page-1)*size math without bounds checks","Prefer Page API which validates both bounds"],"tags":["panache","range","pagination","illegal-argument"],"backgroundTag":"invalid-pagination-index","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"}