{"record":{"id":"b2f847c22cd13682","repo":"pinpoint-apm/pinpoint","slug":"end-index-must-not-be-greater-than-the-array-lengt","errorCode":null,"errorMessage":"End index must not be greater than the array length","messagePattern":"End index must not be greater than the array length","errorType":"exception","errorClass":"ArrayIndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/queue/ArrayViewList.java","lineNumber":34,"sourceCode":" */\n\npackage com.navercorp.pinpoint.profiler.util.queue;\n\nimport java.util.AbstractList;\nimport java.util.Arrays;\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.Objects;\nimport java.util.RandomAccess;\n\npublic class ArrayViewList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable\n{\n    private final E[] array;\n    private final int endIndex;\n\n    public ArrayViewList(E[] array, int endIndex) {\n        if (endIndex > array.length) {\n            throw new ArrayIndexOutOfBoundsException(\"End index must not be greater than the array length\");\n        }\n        this.array = Objects.requireNonNull(array);\n        this.endIndex = endIndex;\n    }\n\n    @Override\n    public boolean add(E e) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public int size() {\n        return endIndex;\n    }\n\n    @Override\n    public Object[] toArray() {\n        return Arrays.copyOf(array, endIndex);","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/util/queue/ArrayViewList.java#L16-L52","documentation":"ArrayViewList is a fixed-size view over an existing array; its constructor validates that endIndex does not exceed array.length. This ArrayIndexOutOfBoundsException is thrown eagerly when constructing a view whose end index would point past the backing array, preventing later reads from escaping array bounds.","triggerScenarios":"Calling new ArrayViewList<>(array, endIndex) where endIndex > array.length, e.g. after computing an end index from a bad size, an off-by-one, or a stale length value.","commonSituations":"Wrapping a circular/flush queue buffer where the stored size was recorded before the array shrank or was reused; off-by-one arithmetic like (start + count) computed on a different array instance.","solutions":["Fix the caller to pass endIndex <= array.length (typically endIndex == array.length or start + size)","Verify the array reference passed is the same one whose length the endIndex was computed from","Add an assertion/log at the call site to capture the array length and endIndex values"],"exampleFix":"// before\nreturn new ArrayViewList<>(buffer, head + size); // head + size may exceed length\n// after\nint endIndex = Math.min(head + size, buffer.length);\nreturn new ArrayViewList<>(buffer, endIndex);","handlingStrategy":"validation","validationCode":"if (endIndex < 0 || endIndex > array.length) throw new IllegalArgumentException(\"endIndex=\" + endIndex + \" length=\" + array.length);\nArrayViewList<E> view = new ArrayViewList<>(array, endIndex);","typeGuard":null,"tryCatchPattern":"try { view = new ArrayViewList<>(array, endIndex); } catch (ArrayIndexOutOfBoundsException e) { log.warn(\"bad endIndex={}, len={}\", endIndex, array.length); view = Collections.emptyList(); }","preventionTips":["Always derive endIndex from the same array instance you pass","Use Math.min(computedEnd, array.length) to clamp","Unit-test queue drain edge cases (empty, full, wrap-around)"],"tags":["java","array","index-out-of-bounds"],"backgroundTag":"index-out-of-bounds","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}