oracle/graal · error · IndexOutOfBoundsException
toIndex = ${toIndex}
Error message
toIndex = ${toIndex} What it means
Thrown by AbstractListWithoutField.subList range checks when toIndex exceeds the list's size. The sublist view must stay inside [0, size]; an end index past the last element is rejected immediately.
Source
Thrown at espresso/src/com.oracle.truffle.espresso.polyglot/src/com/oracle/truffle/espresso/polyglot/collections/AbstractListWithoutField.java:442
* backing list. The {@code iterator} method merely returns {@code listIterator()},
* and the {@code size} method merely returns the subclass's {@code size} field.
*
* @throws IndexOutOfBoundsException if an endpoint index value is out of range
* {@code (fromIndex < 0 || toIndex > size)}
* @throws IllegalArgumentException if the endpoint indices are out of order
* {@code (fromIndex > toIndex)}
*/
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size());
return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex));
}
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0) {
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
}
if (toIndex > size) {
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
}
if (fromIndex > toIndex) {
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
}
// Comparison and hashing
/**
* Compares the specified object with this list for equality. Returns {@code true} if and only
* if the specified object is also a list, both lists have the same size, and all corresponding
* pairs of elements in the two lists are <i>equal</i>. (Two elements {@code e1} and {@code e2}
* are <i>equal</i> if {@code (e1==null ? e2==null :
* e1.equals(e2))}.) In other words, two lists are defined to be equal if they contain the same
* elements in the same order.
*
* @implSpec This implementation first checks if the specified object is this list. If so, itView on GitHub (pinned to a66e9ccd1d)
Solutions
- Clamp the end index: subList(start, Math.min(end, list.size())).
- Re-read size() at the moment of the call rather than caching it.
- For last-page paging compute int end = Math.min(list.size(), start + pageSize).
- Guard with if (from > list.size()) return empty before slicing.
Example fix
// before List<E> page = list.subList(start, start + pageSize); // fails on last page // after int end = Math.min(start + pageSize, list.size()); List<E> page = list.subList(start, end);
Defensive patterns
Strategy: validation
Validate before calling
int end = Math.min(requestedEnd, list.size());
if (fromIndex < 0 || fromIndex > end) {
throw new IllegalArgumentException("bad range: " + fromIndex + ".." + end);
} Prevention
- Always clamp the end index to size() at call time.
- Recompute size() for mutable lists instead of caching.
- Use min(start + pageSize, size) for pagination.
When it happens
Trigger: Calling subList(from, to) with to > size(), e.g. subList(0, 10) on a 5-element list; computing an end offset as start + count without clamping; calling subList on a list that shrank between the size check and the call (concurrent modification).
Common situations: Paging logic 'subList(page * size, (page + 1) * size)' on the last, partial page; slicing a list after another thread removed elements; copying java.util.List sample code onto Espresso collections with different sizes.
Related errors
- fromIndex = ${fromIndex}
- fromIndex(${fromIndex}) > toIndex(${toIndex})
- Index: ${index}, Size: ${size}
- Espresso cannot evaluate Java sources directly, only a few s
- invalid interface type mapping specified: {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/d23d7f00cc9c0524.
Report an issue: GitHub.