oracle/graal · error · IllegalArgumentException

Invalid component type

Error message

Invalid component type

What it means

asArrayConstant(componentType, elements) builds a guest array via a JVMCI helper inside the Espresso VM. The component type's array class must be an EspressoExternalResolvedArrayType — the only implementation that knows the elemental type and dimension count to pass to the guest helper newObjectArray/newPrimitiveArray. A foreign component type has no guest array class, so construction cannot proceed and throws IllegalArgumentException('Invalid component type').

Source

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

    public JavaConstant invoke(ResolvedJavaMethod method, JavaConstant receiver, JavaConstant... arguments) {
        if (!(method instanceof EspressoExternalResolvedJavaMethod espressoMethod)) {
            throw new IllegalArgumentException("Expected an EspressoExternalResolvedJavaMethod, got " + safeGetClass(method));
        }
        return espressoMethod.invoke(receiver, arguments);
    }

    @Override
    public void writeField(ResolvedJavaField field, JavaConstant receiver, JavaConstant value) {
        if (!(field instanceof EspressoExternalResolvedJavaField espressoField)) {
            throw new IllegalArgumentException("Expected an EspressoExternalResolvedJavaField, got " + safeGetClass(field));
        }
        espressoField.writeValue(receiver, value);
    }

    @Override
    public JavaConstant asArrayConstant(ResolvedJavaType componentType, JavaConstant... elements) {
        if (!(componentType.getArrayClass() instanceof EspressoExternalResolvedArrayType arrayType)) {
            throw new IllegalArgumentException("Invalid component type");
        }
        EspressoResolvedJavaType elementalType = arrayType.getElementalType();
        Value array;
        boolean isPrimitiveArray;
        int dimensions = arrayType.getDimensions();
        if (elementalType instanceof EspressoExternalResolvedInstanceType elementalInstanceType) {
            array = invokeJVMCIHelper("newObjectArray", elementalInstanceType.getMetaObject(), dimensions, elements.length);
            isPrimitiveArray = false;
        } else {
            JavaKind javaKind = elementalType.getJavaKind();
            assert javaKind.isPrimitive() && javaKind != JavaKind.Void;
            array = invokeJVMCIHelper("newPrimitiveArray", (int) javaKind.getTypeChar(), dimensions, elements.length);
            isPrimitiveArray = dimensions == 1;
        }
        if (isPrimitiveArray) {
            JavaKind javaKind = elementalType.getJavaKind();
            for (int i = 0; i < elements.length; i++) {
                JavaConstant element = elements[i];

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Resolve componentType through the Espresso external meta access (lookupJavaType on this context) before calling asArrayConstant.
  2. Guard with componentType.getArrayClass() instanceof EspressoExternalResolvedArrayType and fall back to the owning provider otherwise.
  3. Ensure the providers instance passed to EspressoExternalVMAccess is consistent for all type lookups in the call path.

Example fix

// before
JavaConstant arr = vmAccess.asArrayConstant(componentType, elems);

// after
if (componentType.getArrayClass() instanceof EspressoExternalResolvedArrayType) {
    JavaConstant arr = vmAccess.asArrayConstant(componentType, elems);
} else {
    JavaConstant arr = foreignAccess.asArrayConstant(componentType, elems);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(componentType.getArrayClass() instanceof EspressoExternalResolvedArrayType)) {
    // re-resolve componentType through Espresso meta access first
}

Type guard

static boolean isEspressoArrayComponent(ResolvedJavaType t) {
    return t.getArrayClass() instanceof EspressoExternalResolvedArrayType;
}

Try / catch

catch (IllegalArgumentException e) with 'Invalid component type' -> re-lookup the type via lookupJavaType and retry once; otherwise propagate.

Prevention

When it happens

Trigger: Passing a componentType resolved by the host HotSpot meta access or another JVMCI backend; passing a type whose getArrayClass() is not an EspressoExternalResolvedArrayType (e.g. primitive types whose array class is host-built).

Common situations: Building constant arrays for substitutions or folded values with types obtained from the wrong MetaAccessProvider; migrating code from HotSpot JVMCI to Espresso where component types now come from a different source.

Related errors


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