oracle/graal · error · IllegalArgumentException

fromIndex(${fromIndex}) > toIndex(${toIndex})

Error message

fromIndex(${fromIndex}) > toIndex(${toIndex})

What it means

Thrown as IllegalArgumentException by AbstractListWithoutField.subListRangeCheck when fromIndex is greater than toIndex. The interval is ordered: callers must pass start <= end. An inverted range is a logic error distinct from out-of-range indices.

Source

Thrown at espresso/src/com.oracle.truffle.espresso.polyglot/src/com/oracle/truffle/espresso/polyglot/collections/AbstractListWithoutField.java:445

     * @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, it
     *           returns {@code true}; if not, it checks if the specified object is a list. If not,
     *           it returns {@code false}; if so, it iterates over both lists, comparing
     *           corresponding pairs of elements. If any comparison returns {@code false}, this

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Verify fromIndex <= toIndex before the call; swap or reject inverted ranges explicitly.
  2. When computing from a length, clamp: int from = Math.max(0, size - n).
  3. Do not expect negative-index or reversed-slice semantics; normalize ranges first.
  4. Add unit tests covering empty and single-element ranges.

Example fix

// before
List<E> tail = list.subList(list.size() - n, list.size()); // n > size inverts range

// after
int from = Math.max(0, list.size() - n);
List<E> tail = list.subList(from, list.size());
Defensive patterns

Strategy: validation

Validate before calling

if (fromIndex > toIndex) {
    throw new IllegalArgumentException("fromIndex " + fromIndex + " > toIndex " + toIndex);
}

Prevention

When it happens

Trigger: Calling subList(5, 2); computing from = size() - n and to = size() when n > size(); swapping argument order in refactoring; descending ranges expressed as subList(high, low) expecting python-style backwards slices.

Common situations: Porting Python slice semantics (list[5:2]) to Java; off-by-one in computed bounds where from overshoots to; copy-paste between subList(x, y) and other APIs with reversed parameter order.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/4c26f0f8756099c9. Report an issue: GitHub.