oracle/graal · error · IllegalArgumentException

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

Error message

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

What it means

Thrown by EspressoExternalResolvedJavaMethod.invoke's argument marshalling switch when a parameter is declared boolean but the supplied JavaConstant's JavaKind is not Boolean. Unlike the numeric kinds, boolean is not part of JVMCI's widening lattice (booleans are not widened to int in strict invocation, JLS 5.3), so the adapter accepts only an exact Boolean constant and rejects anything else with the parameter index and actual kind in the message.

Source

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

        } else if (!isStatic()) {
            if (!(receiver instanceof EspressoExternalObjectConstant objectConstant)) {
                throw new IllegalArgumentException("Bad receiver: expected Object, got " + arguments[0].getJavaKind());
            }
            args[0] = objectConstant.getValue();
            outputArgumentOffset = 1;
        }
        for (int i = 0; i < parameterCount; i++) {
            JavaConstant argument = arguments[i];
            JavaKind argumentKind = argument.getJavaKind();
            /*
             * Perform widening primitive conversions (JLS 5.1.2) in order to implement strict
             * method invocation conversions (JLS 5.3). Also promote to stack kind.
             */
            args[i + outputArgumentOffset] = switch (signature.getParameterKind(i)) {
                case Boolean -> switch (argumentKind) {
                    case Boolean -> argument.asBoolean() ? 1 : 0;
                    default ->
                        throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Boolean, got " + argumentKind);
                };
                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();

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Convert to JavaConstant.forBoolean(...) at the boundary: check signature.getParameterKind(i)==Boolean and box accordingly
  2. Keep a kind-conversion table mirroring the adapter's switch (Boolean accepts only Boolean) instead of assuming numeric coercion
  3. Fix the producer that promoted the boolean constant to Int

Example fix

// before
args[i] = JavaConstant.forInt(flag ? 1 : 0);
method.invoke(receiver, args);

// after
args[i] = JavaConstant.forBoolean(flag);
method.invoke(receiver, args);
Defensive patterns

Strategy: validation

Validate before calling

if (signature.getParameterKind(i) == JavaKind.Boolean && args[i].getJavaKind() != JavaKind.Boolean) {
    args[i] = JavaConstant.forBoolean(args[i].asInt() != 0);
}

Prevention

When it happens

Trigger: Passing JavaConstant.forInt(0/1), a boxed Boolean wrapped in the wrong constant type, or an Int-kind constant (common because JVMCI promotes subword kinds) to a boolean parameter at the reported index.

Common situations: Constants normalized to Int kind by earlier pipeline stages (stack-kind promotion), replay files that encode booleans as integers, language bridges mapping truthy values to ints.

Related errors


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