oracle/graal · error · NegativeArraySizeException

Negative array size: {}

Error message

Negative array size: {}

What it means

createPrimitiveArray throws NegativeArraySizeException when length < 0, mirroring the standard Java behavior for negative array allocation ('Negative array size: N'). The guest allocation is never attempted; the check is host-side so the error surfaces before any cross-language call.

Source

Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccess.java:584

                    throw new IllegalArgumentException("Element " + i + " should be an espresso object constant, got " + safeGetClass(element));
                }
                try {
                    array.setArrayElement(i, objectElement.getValue());
                } catch (ClassCastException e) {
                    throw new IllegalArgumentException("Element " + i + " is not an instance of the component type", e);
                }
            }
        }
        return new EspressoExternalObjectConstant(this, array);
    }

    @Override
    public JavaConstant createPrimitiveArray(JavaKind kind, int length) {
        if (kind == null || !kind.isPrimitive() || kind == JavaKind.Void) {
            throw new IllegalArgumentException("Expected a non-void primitive kind, got " + kind);
        }
        if (length < 0) {
            throw new NegativeArraySizeException("Negative array size: " + length);
        }
        Value array = invokeJVMCIHelper("newPrimitiveArray", (int) kind.getTypeChar(), 1, length);
        return new EspressoExternalObjectConstant(this, array);
    }

    @Override
    public JavaConstant clonePrimitiveArray(JavaConstant primitiveArray) {
        if (!(primitiveArray instanceof EspressoExternalObjectConstant objectConstant)) {
            throw new IllegalArgumentException("Expected an EspressoExternalObjectConstant, got " + safeGetClass(primitiveArray));
        }
        EspressoResolvedObjectType arrayType = objectConstant.getType();
        if (!(arrayType.isArray() && arrayType.getComponentType().isPrimitive())) {
            throw new IllegalArgumentException("Expected a primitive array constant, got " + arrayType);
        }
        Value copy = invokeJVMCIHelper("clonePrimitiveArray", objectConstant.getValue());
        return new EspressoExternalObjectConstant(this, copy);
    }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Validate length >= 0 before the call and reject/handle the input that produced it.
  2. Clamp or default to 0 when an empty array is acceptable.
  3. Fix the upstream arithmetic (use Math.max(0, n) or explicit bounds checks).

Example fix

// before
JavaConstant a = vmAccess.createPrimitiveArray(JavaKind.Int, list.size() - 1);

// after
int n = Math.max(0, list.size() - 1);
JavaConstant a = vmAccess.createPrimitiveArray(JavaKind.Int, n);
Defensive patterns

Strategy: validation

Validate before calling

if (length < 0) {
    throw new IllegalArgumentException("length must be >= 0: " + length);
}

Try / catch

catch (NegativeArraySizeException e) -> fix the length computation; do not retry with abs().

Prevention

When it happens

Trigger: Passing a computed length that underflows or is derived from unvalidated user input, e.g. size() of an empty collection minus one, or a parsed negative integer.

Common situations: Length arithmetic like list.size() - offset; deserialized or user-supplied dimensions; sign errors when converting unsigned guest values to host ints.

Related errors


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