oracle/graal · error · IllegalArgumentException
Expected a primitive array constant, got {}
Error message
Expected a primitive array constant, got {} What it means
After unwrapping the constant, clonePrimitiveArray verifies the guest type is actually an array with a primitive component (e.g. byte[], int[]). Object arrays and non-array constants are rejected with IllegalArgumentException naming the discovered type, because the guest helper only clones primitive arrays.
Source
Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccess.java:597
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);
}
@Override
public void copyArray(JavaConstant src, int srcPos, JavaConstant dest, int destPos, int length) {
if (!(src instanceof EspressoExternalObjectConstant srcArray)) {
throw new IllegalArgumentException("Expected an EspressoExternalObjectConstant for src, got " + safeGetClass(src));
}
if (!(dest instanceof EspressoExternalObjectConstant destArray)) {
throw new IllegalArgumentException("Expected an EspressoExternalObjectConstant for dest, got " + safeGetClass(dest));
}
if (!srcArray.getType().isArray()) {
throw new IllegalArgumentException("Expected an array constant for src, got " + srcArray.getType());
}
if (!destArray.getType().isArray()) {
throw new IllegalArgumentException("Expected an array constant for dest, got " + destArray.getType());View on GitHub (pinned to a66e9ccd1d)
Solutions
- Check the type first: arrayType.isArray() && arrayType.getComponentType().isPrimitive() (on the constant's Espresso type).
- Use asArrayConstant/copyArray for object arrays instead of clonePrimitiveArray.
- Log the constant's type when the guard fails to find where the wrong array originates.
Example fix
// before
JavaConstant copy = vmAccess.clonePrimitiveArray(arr);
// after
EspressoResolvedObjectType t = ((EspressoExternalObjectConstant) arr).getType();
JavaConstant copy = (t.isArray() && t.getComponentType().isPrimitive())
? vmAccess.clonePrimitiveArray(arr)
: vmAccess.copyArray(arr, 0, vmAccess.createPrimitiveArray(...), 0, len); Defensive patterns
Strategy: validation
Validate before calling
EspressoResolvedObjectType t = ((EspressoExternalObjectConstant) arr).getType();
if (!(t.isArray() && t.getComponentType().isPrimitive())) {
// object array or non-array: use copyArray/asArrayConstant path
} Type guard
static boolean isGuestPrimitiveArray(JavaConstant c) {
if (!(c instanceof EspressoExternalObjectConstant e)) return false;
EspressoResolvedObjectType t = e.getType();
return t.isArray() && t.getComponentType().isPrimitive();
} Try / catch
catch (IllegalArgumentException e) with 'Expected a primitive array constant' -> log the reported type and reroute to the object-array copy path.
Prevention
- Branch on component type before choosing clone vs copy.
- Component-type refactors (primitive -> boxed) must update clone call sites.
- Pass the array, not its element.
When it happens
Trigger: Passing an Espresso object-array constant (String[], Object[]) or a non-array object constant to clonePrimitiveArray.
Common situations: Generic snapshot helpers that assume all arrays are primitive; refactors changing an array's component type from primitive to boxed; passing the array's element instead of the array itself.
Related errors
- Element {} should be a {} but was {}
- Invalid component type
- Element {} should be an espresso object constant, got {}
- Element {} is not an instance of the component type
- Expected a non-void primitive kind, got {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/0c6a9ec9d925a28b.
Report an issue: GitHub.