oracle/graal · error · IllegalArgumentException

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

Error message

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

What it means

Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared long but the argument constant's kind is not in {Long, Int, Char, Short, Byte}. All subword integral kinds widen to long (JLS 5.1.2); Float, Double, Boolean, and Object constants are rejected because converting them to long is either lossy or invalid under strict invocation. The index in the message identifies which parameter mismatches.

Source

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

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

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Convert explicitly when narrowing from double: JavaConstant.forLong((long) d.asDouble())
  2. Verify the argument array is aligned to getSignature().getParameterCount(false) with no receiver included
  3. If a Float constant is intended for a long parameter, rebox via forLong(argument.asLong()-compatible path) after explicit cast

Example fix

// before
args[i] = JavaConstant.forDouble(seconds); // parameter is long

// after
args[i] = JavaConstant.forLong((long) seconds);
Defensive patterns

Strategy: validation

Validate before calling

JavaKind ak = args[i].getJavaKind();
if (signature.getParameterKind(i) == JavaKind.Long && !(ak == JavaKind.Long || ak == JavaKind.Int || ak == JavaKind.Char || ak == JavaKind.Short || ak == JavaKind.Byte)) {
    throw new IllegalStateException("argument " + i + " cannot widen to long; got " + ak);
}

Prevention

When it happens

Trigger: Passing JavaConstant.forDouble/forFloat to a long parameter; passing a Boolean constant; passing an EspressoExternalObjectConstant where a long is declared (argument order shifted).

Common situations: Argument array misalignment (extra/missing element earlier shifts an Object into a long slot); signature drift between guest class versions; interop bridges that represent all numbers as doubles.

Related errors


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