oracle/graal · error · IllegalArgumentException

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

Error message

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

What it means

Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared short but the argument constant's kind is neither Short nor Byte. The adapter implements JLS 5.1.2 widening for subwords: short accepts byte (widening byte-to-short), but rejects Int, Char, Long, etc. — narrowing (e.g. int to short) is not strict invocation and would silently truncate, so it fails fast with the index and offending kind.

Source

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

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

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Narrow explicitly first: JavaConstant.forShort((short) c.asInt()) for short parameters
  2. Keep Byte constants as-is (they are accepted) but rebox Int/Char to Short
  3. Add a signature-driven conversion pass before invoke instead of ad-hoc reboxing at each call site

Example fix

// before
args[i] = JavaConstant.forInt(count); // parameter is short

// after
args[i] = JavaConstant.forShort((short) count);
Defensive patterns

Strategy: validation

Validate before calling

JavaKind pk = signature.getParameterKind(i);
if (pk == JavaKind.Short) {
    JavaKind ak = args[i].getJavaKind();
    if (ak != JavaKind.Short && ak != JavaKind.Byte) {
        args[i] = JavaConstant.forShort((short) args[i].asInt());
    }
}

Prevention

When it happens

Trigger: Passing JavaConstant.forInt(x) to a short parameter (intentional narrowing is not supported); passing a Char or Long constant; constants already promoted to stack kind Int by earlier JVMCI stages.

Common situations: Callers assuming implicit narrowing like Java casts; replaying values stored as ints; generic bridges that only produce Int constants for all integral types.

Related errors


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