oracle/graal · error · IllegalArgumentException

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

Error message

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

What it means

Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared int but the argument constant's kind is not one of Int, Char, Short, Byte. The adapter widens all subword integral kinds to int (JLS 5.1.2), matching bytecode stack semantics, but rejects Long, Float, Double, Boolean, and Object constants — those cannot reach an int parameter under strict invocation without an explicit cast.

Source

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

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

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Convert explicitly: JavaConstant.forInt((int) c.asLong()) when the narrowing is intended
  2. Re-resolve the method signature if a guest class changed a parameter type
  3. Double-check argument index alignment — an off-by-one shift often surfaces as this error at an unexpected index

Example fix

// before
args[i] = JavaConstant.forLong(v); // parameter is int

// after
args[i] = JavaConstant.forInt((int) v);
Defensive patterns

Strategy: validation

Validate before calling

JavaKind pk = signature.getParameterKind(i);
if (pk == JavaKind.Int && args[i].getJavaKind() != JavaKind.Int
    && args[i].getJavaKind().isPrimitiveWord
    && args[i].getJavaKind() != JavaKind.Long /* Long needs explicit cast */) {
    args[i] = JavaConstant.forInt(args[i].asInt());
}

Prevention

When it happens

Trigger: Passing a Long constant (e.g. from a long literal or forLong-based helper) to an int parameter; passing a Boolean or object constant where an int is declared; Float/Double constants for an int slot.

Common situations: APIs that changed a parameter from long to int (or vice versa) between guest versions while callers kept forLong; uniform long-based constant helpers; misaligned argument arrays after an arity fix.

Related errors


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