oracle/graal · error · IllegalArgumentException

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

Error message

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

What it means

Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared byte but the argument constant's kind is not Byte. Byte is a source kind in JVMCI (not a stack kind), so constants easily lose it: most JVMCI utilities store bytes as Int constants. The adapter's switch is deliberately conservative for subword target types — only Int, Char, Short, and Float/Double parameters accept wider input sets; a Byte parameter demands a Byte constant.

Source

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

            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();
                    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();

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Rebox to the parameter kind with JavaConstant.forByte((byte) c.asInt()) before invoke
  2. Drive conversion from signature.getParameterKind(i) so each subword kind is restored after stack promotion
  3. Avoid generic 'normalize to Int' helpers on argument arrays destined for this API

Example fix

// before
args[i] = JavaConstant.forInt(b); // parameter is byte

// after
args[i] = JavaConstant.forByte((byte) b);
Defensive patterns

Strategy: validation

Validate before calling

if (signature.getParameterKind(i) == JavaKind.Byte && args[i].getJavaKind() != JavaKind.Byte) {
    args[i] = JavaConstant.forByte((byte) args[i].asInt());
}

Prevention

When it happens

Trigger: Passing JavaConstant.forInt(0x7F) or a constant that came off the JVMCI stack (where byte is promoted to int) to a byte parameter at the reported index.

Common situations: Replaying bytecode-level values through the adapter; pipelines that rebox constants via asInt(); interop from languages without a distinct byte type.

Related errors


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