oracle/graal · error · IllegalArgumentException

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

Error message

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

What it means

Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared char but the argument constant's kind is not Char. Char accepts no widening inputs in the adapter (a Char parameter requires a Char constant; only Int/Long/Float/Double parameters accept Char as input), because strict invocation (JLS 5.3) does not widen int to char. Char is also a subword source kind that JVMCI often promotes to Int, making this easy to hit after stack-kind normalization.

Source

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

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

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Rebox with JavaConstant.forChar((char) c.asInt()) for char parameters
  2. Branch on signature.getParameterKind(i) to preserve Char constants through your pipeline
  3. Fix producers that call JavaConstant.forInt on character data

Example fix

// before
args[i] = JavaConstant.forInt(codePoint); // parameter is char

// after
args[i] = JavaConstant.forChar((char) codePoint);
Defensive patterns

Strategy: validation

Validate before calling

if (signature.getParameterKind(i) == JavaKind.Char && args[i].getJavaKind() != JavaKind.Char) {
    args[i] = JavaConstant.forChar((char) args[i].asInt());
}

Prevention

When it happens

Trigger: Passing JavaConstant.forInt(65) or forShort(...) to a char parameter; constants read from a JVMCI frame or produced by ConstantReflectionProvider.boxAsKind with Int kind.

Common situations: Interop layers converting characters to ints; replay/snapshot tooling storing chars as ints; constants that passed through asInt()-based reboxing.

Related errors


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