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.

Solutions

  1. Match the constant factory to the component kind: use JavaConstant.forInt/forLong/forDouble etc. according to arrayType.getComponentType().getJavaKind()
  2. Before writing, branch on the component kind and convert the value (e.g. JavaConstant.forLong(element.asInt()) when storing into a long[])
  3. 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

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


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

Appendix: 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)