oracle/graal · error · IllegalArgumentException

Expected an EspressoExternalObjectConstant for dest, got

Error message

Expected an EspressoExternalObjectConstant for dest, got 

What it means

The destination side of copyArray must equally be an EspressoExternalObjectConstant wrapping a guest array, because System.arraycopy executes inside the guest Espresso VM and can only store into guest memory. A dest constant from a foreign backend is rejected with IllegalArgumentException('Expected an EspressoExternalObjectConstant for dest, ...') before any copy is attempted, so no partial write can occur.

Solutions

  1. Allocate the destination through this Espresso provider (createPrimitiveArray / asArrayConstant) before copyArray.
  2. Guard dest instanceof EspressoExternalObjectConstant; otherwise copy into the host array with System.arraycopy after unwrapping the source values.
  3. Keep allocation and copy on the same side of the host/guest boundary.

Example fix

// before
JavaConstant dest = JavaConstant.forObject(new byte[n]);
vmAccess.copyArray(src, 0, dest, 0, n);

// after
JavaConstant dest = vmAccess.createPrimitiveArray(JavaKind.Byte, n);
vmAccess.copyArray(src, 0, dest, 0, n);
Defensive patterns

Strategy: validation

Validate before calling

if (!(dest instanceof EspressoExternalObjectConstant)) {
    dest = vmAccess.createPrimitiveArray(kind, length); // guest-allocated destination
}

Type guard

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

Try / catch

catch (IllegalArgumentException e) with 'for dest' -> allocate dest via createPrimitiveArray/asArrayConstant and retry the copy.

Prevention

When it happens

Trigger: Copying guest data into a destination allocated by the host provider (JavaConstant.forObject(hostArray)) or by another Espresso context.

Common situations: Result buffers pre-allocated on the host and passed into guest copy routines; mixed provider usage in buffer management code.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/31cf3e7af5d67ae4. 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:609

    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()) {
            throw new IllegalArgumentException("Expected an array constant for src, got " + srcArray.getType());
        }
        if (!destArray.getType().isArray()) {
            throw new IllegalArgumentException("Expected an array constant for dest, got " + destArray.getType());
        }
        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

View on GitHub (pinned to a66e9ccd1d)