oracle/graal · warning · ArrayIndexOutOfBoundsException
Index should be an int
Error message
Index should be an int
What it means
ArrayIndexOutOfBoundsException ('Index should be an int') thrown by the ProxyArray view of a host object's member keys in EspressoExternalHostProxies.getMemberKeys: the polyglot long index passed to get(long) overflows int range, so Math.toIntExact(index) throws ArithmeticException, which is converted to this AIOOBE. Polyglot array indices are longs, but the backing Java key array is indexed by int, so any index outside [0, Integer.MAX_VALUE] (including negatives or values > 2^31-1) cannot be served.
Source
Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalHostProxies.java:363
private Value computeGuestMethodMap(Class<?> hostClass, EspressoExternalResolvedInstanceType guestType) {
Map<String, ProxyExecutable> map = computeMethodMap(hostClass, guestType);
ProxyObject invocables = new ProxyObject() {
@Override
public Object getMember(String key) {
return map.get(key);
}
@Override
public Object getMemberKeys() {
Object[] keys = map.keySet().toArray();
return new ProxyArray() {
@Override
public Object get(long index) {
try {
return keys[Math.toIntExact(index)];
} catch (ArithmeticException e) {
throw new ArrayIndexOutOfBoundsException("Index should be an int");
}
}
@Override
public void set(long index, Value value) {
throw new UnsupportedOperationException("set() not supported.");
}
@Override
public long getSize() {
return keys.length;
}
};
}
@Override
public boolean hasMember(String key) {
return map.containsKey(key);View on GitHub (pinned to a66e9ccd1d)
Solutions
- Guest-side: clamp/validate indices to 0 <= index < getSize() before accessing member keys.
- Host-side: treat this exception as 'index out of the representable range' and return undefined/holes for huge indices instead of failing the iteration.
- If a guest engine probes with sentinel indices, ensure the engine's interop layer is current — newer Truffle versions probe less aggressively.
- Report a bug only if the index is within [0, size) and still fails; that would indicate a genuine provider defect.
Example fix
// before (guest interop caller) for (let i = 0; i < 2 ** 33; i++) readKeyAt(i); // long probe hits get(Long.MAX) // after const n = memberKeys.getSize(); // long for (let i = 0; i < n && i < 2147483647; i++) readKeyAt(i);
Defensive patterns
Strategy: validation
Validate before calling
// guest/interop side: bounds-check against size before read
long n = memberKeys.getSize();
if (index < 0 || index >= n || index > Integer.MAX_VALUE) {
return undefinedOrError(index); // out of representable range
}
return memberKeys.get(index); Try / catch
try { return keysProxy.get(idx); } catch (ArrayIndexOutOfBoundsException e) { /* index not representable as int: treat as hole/undefined */ } Prevention
- Clamp guest array access on interop mirrors to 0 <= index < size.
- Do not pass sentinel/probe indices (e.g. Long.MAX_VALUE) into polyglot array reads.
- Keep Truffle/guest-engine versions current to avoid aggressive sparse-array probing.
When it happens
Trigger: Guest language code iterating the array-shaped mirror of a host object's member keys with an index larger than Integer.MAX_VALUE or negative; a guest runtime probing ProxyArray.getSize/get bounds incorrectly and calling get() with a huge sentinel index.
Common situations: JS or other guest engines performing sparse-array probing (reading index 2^32 or beyond to detect array holes); guest code passing an unvalidated user-supplied index straight into the polyglot array access; interop with languages whose arrays are long-indexed (e.g. some native engines).
Related errors
- set() not supported.
- UnsupportedTypeException serialization is not supported.
- putMember() not supported.
- Cannot find partial evaluation configuration: %s
- Invalid option
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/026b1f29cfebb1c6.
Report an issue: GitHub.