oracle/graal · error · IllegalArgumentException

Bad argument kind at index {}: expected Double, got {}

Error message

Bad argument kind at index {}: expected Double, got {}

What it means

Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared double but the argument constant's kind is not in {Long, Int, Char, Short, Byte, Float, Double}. This is the widest numeric acceptance set (everything numeric widens to double, JLS 5.1.2); only Boolean and Object constants are rejected, since neither is convertible to double under strict invocation. Hitting it usually means an argument order problem or a wrong method resolved rather than a genuine conversion gap.

Source

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

                        throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Int, got " + argumentKind);
                };
                case Long -> switch (argumentKind) {
                    case Long, Int, Char, Short, Byte -> argument.asLong();
                    default ->
                        throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Long, got " + argumentKind);
                };
                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) {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Recheck argument alignment: receiver excluded, arity equals getParameterCount(false), each constant matches its parameter position
  2. Verify the resolved ResolvedJavaMethod is the intended overload (compare name and signature)
  3. Convert Boolean constants to a numeric double explicitly if the guest API really takes double for a truth flag

Example fix

// before: receiver accidentally left in args
JavaConstant[] args = {receiver, JavaConstant.forDouble(x)};
method.invoke(null, args); // instance method -> misaligned

// after
JavaConstant[] args = {JavaConstant.forDouble(x)};
method.invoke(receiver, args);
Defensive patterns

Strategy: validation

Validate before calling

JavaKind ak = args[i].getJavaKind();
boolean numeric = ak == JavaKind.Double || ak == JavaKind.Float || ak == JavaKind.Long || ak == JavaKind.Int || ak == JavaKind.Char || ak == JavaKind.Short || ak == JavaKind.Byte;
if (signature.getParameterKind(i) == JavaKind.Double && !numeric) {
    throw new IllegalStateException("argument " + i + " not numeric for double parameter");
}

Prevention

When it happens

Trigger: Passing a Boolean constant to a double parameter; passing an EspressoExternalObjectConstant (object) where a double is declared; argument array shifted by including the receiver or dropping an argument.

Common situations: Off-by-one argument alignment after adapting from java.lang.reflect.Method.invoke; resolving an overload with a different signature than intended; polymorphic call sites mis-dispatched.

Related errors


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