{"record":{"id":"d862661ec8885a66","repo":"oracle/graal","slug":"bad-argument-kind-at-index-expected-short-got","errorCode":null,"errorMessage":"Bad argument kind at index {}: expected Short, got {}","messagePattern":"Bad argument kind at index (.+?): expected Short, got (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaMethod.java","lineNumber":338,"sourceCode":"                case Boolean -> switch (argumentKind) {\n                    case Boolean -> argument.asBoolean() ? 1 : 0;\n                    default ->\n                        throw new IllegalArgumentException(\"Bad argument kind at index \" + i + \": expected Boolean, got \" + argumentKind);\n                };\n                case Byte -> switch (argumentKind) {\n                    case Byte -> argument.asInt();\n                    default ->\n                        throw new IllegalArgumentException(\"Bad argument kind at index \" + i + \": expected Byte, got \" + argumentKind);\n                };\n                case Char -> switch (argumentKind) {\n                    case Char -> argument.asInt();\n                    default ->\n                        throw new IllegalArgumentException(\"Bad argument kind at index \" + i + \": expected Char, got \" + argumentKind);\n                };\n                case Short -> switch (argumentKind) {\n                    case Short, Byte -> argument.asInt();\n                    default ->\n                        throw new IllegalArgumentException(\"Bad argument kind at index \" + i + \": expected Short, got \" + argumentKind);\n                };\n                case Int -> switch (argumentKind) {\n                    case Int, Char, Short, Byte -> argument.asInt();\n                    default ->\n                        throw new IllegalArgumentException(\"Bad argument kind at index \" + i + \": expected Int, got \" + argumentKind);\n                };\n                case Long -> switch (argumentKind) {\n                    case Long, Int, Char, Short, Byte -> argument.asLong();\n                    default ->\n                        throw new IllegalArgumentException(\"Bad argument kind at index \" + i + \": expected Long, got \" + argumentKind);\n                };\n                case Float -> switch (argumentKind) {\n                    case Long, Int, Char, Short, Byte -> (float) argument.asLong();\n                    case Float -> argument.asFloat();\n                    default ->\n                        throw new IllegalArgumentException(\"Bad argument kind at index \" + i + \": expected Float, got \" + argumentKind);\n                };\n                case Double -> switch (argumentKind) {","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaMethod.java#L320-L356","documentation":"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.","triggerScenarios":"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.","commonSituations":"Callers assuming implicit narrowing like Java casts; replaying values stored as ints; generic bridges that only produce Int constants for all integral types.","solutions":["Narrow explicitly first: JavaConstant.forShort((short) c.asInt()) for short parameters","Keep Byte constants as-is (they are accepted) but rebox Int/Char to Short","Add a signature-driven conversion pass before invoke instead of ad-hoc reboxing at each call site"],"exampleFix":"// before\nargs[i] = JavaConstant.forInt(count); // parameter is short\n\n// after\nargs[i] = JavaConstant.forShort((short) count);","handlingStrategy":"validation","validationCode":"JavaKind pk = signature.getParameterKind(i);\nif (pk == JavaKind.Short) {\n    JavaKind ak = args[i].getJavaKind();\n    if (ak != JavaKind.Short && ak != JavaKind.Byte) {\n        args[i] = JavaConstant.forShort((short) args[i].asInt());\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Short accepts only Short and Byte; explicit narrowing from Int is the caller's job","Never assume cast-like narrowing in strict invocation adapters","Use a signature-driven conversion table matching the adapter's switch"],"tags":["espresso","jvmci","method-invocation","javakind","short","narrowing"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}