oracle/graal · error · IllegalArgumentException

Expected an EspressoExternalObjectConstant, got

Error message

Expected an EspressoExternalObjectConstant, got {}

What it means

clonePrimitiveArray(primitiveArray) deep-copies a guest primitive array by unwrapping an EspressoExternalObjectConstant and calling the guest helper clonePrimitiveArray. A constant from any other JVMCI backend has no guest Value to clone, so it is rejected with IllegalArgumentException before the helper is invoked.

Solutions

  1. Only clone arrays originally created by this Espresso provider (createPrimitiveArray / asArrayConstant results).
  2. Guard with primitiveArray instanceof EspressoExternalObjectConstant and use host-side clone() for host arrays.
  3. Keep constants tagged with their originating provider in caches to avoid cross-provider leakage.

Example fix

// before
JavaConstant copy = vmAccess.clonePrimitiveArray(maybeHostConstant);

// after
JavaConstant copy = (maybeHostConstant instanceof EspressoExternalObjectConstant)
        ? vmAccess.clonePrimitiveArray(maybeHostConstant)
        : hostCopy(maybeHostConstant);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(primitiveArray instanceof EspressoExternalObjectConstant)) {
    // host array: clone on the host instead
}

Type guard

static boolean isEspressoConstant(JavaConstant c) {
    return c instanceof EspressoExternalObjectConstant;
}

Try / catch

catch (IllegalArgumentException e) with 'Expected an EspressoExternalObjectConstant' -> clone host arrays with .clone(), guest arrays via the provider.

Prevention

When it happens

Trigger: Passing a host-created array constant (JavaConstant.forObject(byte[]) or HotSpot constant) or a constant from another Espresso context to clonePrimitiveArray.

Common situations: Copy-on-write snapshot logic that sometimes receives host arrays; caching constants across provider lifecycles; tests with hand-built constants.

Related errors


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

Appendix: source

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

        return new EspressoExternalObjectConstant(this, array);
    }

    @Override
    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()) {

View on GitHub (pinned to a66e9ccd1d)