oracle/graal · error · IllegalArgumentException

Expected an array type, got

Error message

Expected an array type, got 

What it means

After unwrapping the constant, writeArrayElement requires its guest type to be an array type (isArray()) before reading the component type and performing the store. Writing into a non-array Espresso constant (a plain object, string, or class mirror) throws IllegalArgumentException('Expected an array type, ...') naming the actual type.

Source

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

        }
        try {
            invoke(java_lang_System_arraycopy, null, srcArray, JavaConstant.forInt(srcPos), destArray, JavaConstant.forInt(destPos), JavaConstant.forInt(length));
        } catch (InvocationException e) {
            if (e.getCause() instanceof PolyglotException polyglotException) {
                throw throwHostException(polyglotException);
            }
            throw e;
        }
    }

    @Override
    public void writeArrayElement(JavaConstant array, int index, JavaConstant element) {
        if (!(array instanceof EspressoExternalObjectConstant espressoArray)) {
            throw new IllegalArgumentException("Expected an EspressoExternalObjectConstant, got " + safeGetClass(array));
        }
        EspressoResolvedObjectType arrayType = espressoArray.getType();
        if (!arrayType.isArray()) {
            throw new IllegalArgumentException("Expected an array type, got " + arrayType);
        }
        ResolvedJavaType componentType = arrayType.getComponentType();
        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.isNull()) {
            unwrappedValue = null;
        } else {
            if (!(element instanceof EspressoExternalObjectConstant objectElement)) {
                throw new IllegalArgumentException("Element " + element + " should be an espresso object constant, got " + safeGetClass(element));
            }
            unwrappedValue = objectElement.getValue();
        }
        try {
            espressoArray.getValue().setArrayElement(index, unwrappedValue);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Check the constant's type with isArray() (on EspressoExternalObjectConstant.getType()) before the store.
  2. Ensure the array is allocated (createPrimitiveArray / asArrayConstant) before the first writeArrayElement.
  3. Log the type on guard failure to trace where the scalar constant was produced.

Example fix

// before
vmAccess.writeArrayElement(scalarConstant, 0, element);

// after
EspressoExternalObjectConstant arr = (EspressoExternalObjectConstant) constant;
if (arr.getType().isArray()) {
    vmAccess.writeArrayElement(arr, 0, element);
}
Defensive patterns

Strategy: validation

Validate before calling

if (array instanceof EspressoExternalObjectConstant e && !e.getType().isArray()) {
    // scalar constant passed by mistake — resolve the intended array constant
}

Type guard

static boolean isGuestArray(JavaConstant c) {
    return c instanceof EspressoExternalObjectConstant e && e.getType().isArray();
}

Prevention

When it happens

Trigger: Passing a scalar Espresso object constant, a String constant, or a mirror object where an array constant is expected.

Common situations: Element/enclosing-array variable confusion; placeholders passed before allocation; JSON/descriptor-driven store logic that mislabels fields as arrays.

Related errors


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