oracle/graal · error · IllegalArgumentException

Bad argument kind at index {}: expected Object, got {} wrapp

Error message

Bad argument kind at index {}: expected Object, got {} wrapped in a {}

What it means

Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared Object (reference type) and the argument is neither null nor an EspressoExternalObjectConstant. Null yields Java null for the guest call; non-null reference arguments must carry a guest polyglot Value, which only EspressoExternalObjectConstant provides. The message reports both the constant's JavaKind and its concrete class, distinguishing 'wrong kind' (e.g. an Int passed for a String parameter) from 'wrong provenance' (a foreign object constant).

Source

Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaMethod.java:368

                case Float -> switch (argumentKind) {
                    case Long, Int, Char, Short, Byte -> (float) argument.asLong();
                    case Float -> argument.asFloat();
                    default ->
                        throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Float, got " + argumentKind);
                };
                case Double -> switch (argumentKind) {
                    case Long, Int, Char, Short, Byte -> (double) argument.asLong();
                    case Float -> (double) argument.asFloat();
                    case Double -> argument.asDouble();
                    default ->
                        throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Double, got " + argumentKind);
                };
                case Object -> {
                    if (argument.isNull()) {
                        yield null;
                    }
                    if (!(argument instanceof EspressoExternalObjectConstant objectConstant)) {
                        throw new IllegalArgumentException(
                                        "Bad argument kind at index " + i + ": expected Object, got " + argumentKind + " wrapped in a " + argument.getClass().getName());
                    }
                    yield objectConstant.getValue();
                }
                default -> JVMCIError.shouldNotReachHere(signature.getParameterKind(i).toString());
            };
        }
        Value result;
        try {
            result = vmMethodMirror.execute(args);
        } catch (PolyglotException e) {
            if (e.isHostException()) {
                Throwable hostException = e.asHostException();
                hostException.setStackTrace(e.getStackTrace());
                throw new InvocationException(hostException);
            }
            Value guestException = e.getGuestObject();
            if (guestException == null || guestException.isNull()) {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. For guest objects, obtain constants via the Espresso constant/snippet reflection so they are EspressoExternalObjectConstant
  2. For boxed types, invoke the guest valueOf method (or pass an EspressoExternalObjectConstant wrapping a guest boxed value) — no autoboxing happens implicitly
  3. If the reported kind is primitive, re-check argument order/arity first

Example fix

// before
args[i] = JavaConstant.forInt(42); // parameter is java.lang.Integer

// after
JavaConstant boxed = espressoMethod.valueOf.invoke(null, JavaConstant.forInt(42)); // guest Integer.valueOf
args[i] = boxed;
Defensive patterns

Strategy: validation

Validate before calling

if (signature.getParameterKind(i) == JavaKind.Object) {
    JavaConstant a = args[i];
    if (!a.isNull() && !(a instanceof EspressoExternalObjectConstant)) {
        throw new IllegalStateException("argument " + i + " must be null or an Espresso object constant, got " + a.getClass().getName());
    }
}

Prevention

When it happens

Trigger: Passing a primitive constant to a reference parameter (kind mismatch, often argument misalignment); passing a host-backend object constant (provenance mismatch); passing a primitive wrapper constant where the guest method expects a boxed java.lang.Integer (the adapter does not autobox).

Common situations: Host-to-guest bridging without converting objects to guest Values; autoboxing assumptions (int -> java.lang.Integer is not performed); overload resolution picking the boxed-parameter variant of a method.

Related errors


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