oracle/graal · error · IndexOutOfBoundsException
fromIndex = ${fromIndex}
Error message
fromIndex = ${fromIndex} What it means
Thrown by AbstractListWithoutField.subList range checks when the start index is negative. It mirrors java.util.AbstractList semantics: subList(fromIndex, toIndex) requires 0 <= fromIndex <= toIndex <= size. A negative fromIndex is rejected before any sublist view is created.
Source
Thrown at espresso/src/com.oracle.truffle.espresso.polyglot/src/com/oracle/truffle/espresso/polyglot/collections/AbstractListWithoutField.java:439
* <p>
* The {@code listIterator(int)} method returns a "wrapper object" over a list
* iterator on the backing list, which is created with the corresponding method on the
* 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 sameView on GitHub (pinned to a66e9ccd1d)
Solutions
- Validate fromIndex >= 0 before calling subList and clamp to 0 when appropriate.
- Check for -1 sentinels (indexOf, lastIndexOf) before using them as fromIndex.
- Use Math.max(0, fromIndex) when a clamped window is acceptable.
- Wrap the call in try-catch on IndexOutOfBoundsException at API boundaries that accept raw user input.
Example fix
// before List<E> page = list.subList(start, end); // start can be -1 from lastIndexOf // after int start = Math.max(0, rawStart); if (rawStart == -1 /* not found */) return List.of(); List<E> page = list.subList(start, Math.max(start, end));
Defensive patterns
Strategy: validation
Validate before calling
if (fromIndex < 0 || toIndex > list.size() || fromIndex > toIndex) {
throw new IllegalArgumentException("bad range: " + fromIndex + ".." + toIndex + " of " + list.size());
} Prevention
- Centralize sublist bounds checks in one helper used everywhere.
- Treat -1 search results as 'not found', never as an index.
- Unit-test boundary ranges (0, size, size+1, inverted).
When it happens
Trigger: Calling subList(negative, n) on any Espresso polyglot collections list (e.g. list.subList(-1, 3)); computing an offset that underflows (start - 1 when start == 0); passing a user-supplied paging start index without clamping.
Common situations: Pagination code computing 'int start = page * pageSize - pageSize' that goes negative for page 0; passing an index derived from lastIndexOf (which returns -1 on miss) directly to subList.
Related errors
- toIndex = ${toIndex}
- 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/1fb6ff4d9d8a24ee.
Report an issue: GitHub.