oracle/graal · error · IllegalArgumentException
Element {} should be a {}, got {}
Error message
Element {} should be a {}, got {} What it means
Thrown by HostVMAccess.writeArrayElement when the target array has a primitive component type but the JavaConstant element has a different JavaKind (e.g. writing a JavaKind.Int constant into an int[] is fine, but writing JavaKind.Long into int[] fails). The host-mode VMAccess implementation unwraps the element with asBoxedPrimitive(), which requires the kinds to match exactly. There is no implicit numeric conversion.
Source
Thrown at compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java:345
@Override
public void copyArray(JavaConstant src, int srcPos, JavaConstant dest, int destPos, int length) {
Object srcArray = providers.getSnippetReflection().asObject(Object.class, src);
if (srcArray == null || !srcArray.getClass().isArray()) {
throw new IllegalArgumentException("Expected an array constant for src, got " + src);
}
Object destArray = providers.getSnippetReflection().asObject(Object.class, dest);
if (destArray == null || !destArray.getClass().isArray()) {
throw new IllegalArgumentException("Expected an array constant for dest, got " + dest);
}
System.arraycopy(srcArray, srcPos, destArray, destPos, length);
}
private void doWriteArrayElement(Object array, ResolvedJavaType componentType, int index, JavaConstant element) {
Object unwrappedValue;
if (componentType.isPrimitive()) {
if (componentType.getJavaKind() != element.getJavaKind()) {
throw new IllegalArgumentException("Element " + element + " should be a " + componentType.getJavaKind() + ", got " + element.getJavaKind());
}
unwrappedValue = element.asBoxedPrimitive();
} else {
if (!element.getJavaKind().isObject()) {
throw new IllegalArgumentException("Element " + element + " should be an object, got " + componentType);
}
unwrappedValue = providers.getSnippetReflection().asObject(Object.class, element);
}
Array.set(array, index, unwrappedValue);
}
@Override
public void writeArrayElement(JavaConstant array, int index, JavaConstant element) {
ResolvedJavaType arrayType = getProviders().getMetaAccess().lookupJavaType(array);
if (arrayType == null || !arrayType.isArray()) {
throw new IllegalArgumentException("Expected an array constant, got " + array);
}
Object asObject = providers.getSnippetReflection().asObject(Object.class, array);View on GitHub (pinned to a66e9ccd1d)
Solutions
- Match the constant factory to the component kind: use JavaConstant.forInt/forLong/forDouble etc. according to arrayType.getComponentType().getJavaKind()
- Before writing, branch on the component kind and convert the value (e.g. JavaConstant.forLong(element.asInt()) when storing into a long[])
- If the value is genuinely dynamic, validate element.getJavaKind() == componentType.getJavaKind() and fail early with your own error message
Example fix
// before
vmAccess.writeArrayElement(intArrayConst, 0, JavaConstant.forLong(42));
// after
JavaKind kind = metaAccess.lookupJavaType(intArrayConst).getComponentType().getJavaKind();
JavaConstant element = switch (kind) {
case Int -> JavaConstant.forInt(42);
case Long -> JavaConstant.forLong(42);
default -> throw new IllegalStateException("Unhandled kind " + kind);
};
vmAccess.writeArrayElement(intArrayConst, 0, element); Defensive patterns
Strategy: type-guard
Validate before calling
JavaKind component = providers.getMetaAccess().lookupJavaType(arrayConst).getComponentType().getJavaKind();
if (component.isPrimitive() && elementConst.getJavaKind() != component) {
throw new IllegalArgumentException("Element kind " + elementConst.getJavaKind() + " != component kind " + component);
} Type guard
boolean kindsMatch(JavaConstant array, JavaConstant element, MetaAccessProvider meta) {
ResolvedJavaType t = meta.lookupJavaType(array);
return t != null && t.isArray() && t.getComponentType().getJavaKind() == element.getJavaKind();
} Try / catch
catch (IllegalArgumentException e) when message starts with "Element " and contains "should be a": rethrow with caller context (array type + element constant).
Prevention
- Always derive the JavaConstant factory from the component JavaKind, never hardcode it
- Centralize array-element writes in one helper that kind-checks once
- In tests, assert kind equality before writing to catch fixture drift
When it happens
Trigger: Calling VMAccess.writeArrayElement(arrayConstant, index, element) where metaAccess.lookupJavaType(array).getComponentType().isPrimitive() is true but componentType.getJavaKind() != element.getJavaKind(). Example: writing JavaConstant.forInt(1) into a long[] constant, or a forDouble constant into a float[].
Common situations: Generically forwarding constants from parsed bytecode or a serializer that assumes the JVM widens/narrows primitives; building test fixtures where the array kind and the constant factory (forInt vs forLong vs forShort) get out of sync.
Related errors
- Element {} should be an object, got {}
- Expected an array constant, got {}
- Illegal argument type: arguments[{}] of type {} could not be
- Illegal argument type: receiver of type {} could not be conv
- Expected value kind {} but got {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/3b31cf2d306fb8bd.
Report an issue: GitHub.