{"record":{"id":"8eeeb8c4d35ddc35","repo":"oracle/graal","slug":"bad-argument-kind-at-index-expected-byte-got","errorCode":null,"errorMessage":"Bad argument kind at index {}: expected Byte, got {}","messagePattern":"Bad argument kind at index (.+?): expected Byte, 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":328,"sourceCode":"            outputArgumentOffset = 1;\n        }\n        for (int i = 0; i < parameterCount; i++) {\n            JavaConstant argument = arguments[i];\n            JavaKind argumentKind = argument.getJavaKind();\n            /*\n             * Perform widening primitive conversions (JLS 5.1.2) in order to implement strict\n             * method invocation conversions (JLS 5.3). Also promote to stack kind.\n             */\n            args[i + outputArgumentOffset] = switch (signature.getParameterKind(i)) {\n                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();","sourceCodeStart":310,"sourceCodeEnd":346,"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#L310-L346","documentation":"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.","triggerScenarios":"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.","commonSituations":"Replaying bytecode-level values through the adapter; pipelines that rebox constants via asInt(); interop from languages without a distinct byte type.","solutions":["Rebox to the parameter kind with JavaConstant.forByte((byte) c.asInt()) before invoke","Drive conversion from signature.getParameterKind(i) so each subword kind is restored after stack promotion","Avoid generic 'normalize to Int' helpers on argument arrays destined for this API"],"exampleFix":"// before\nargs[i] = JavaConstant.forInt(b); // parameter is byte\n\n// after\nargs[i] = JavaConstant.forByte((byte) b);","handlingStrategy":"validation","validationCode":"if (signature.getParameterKind(i) == JavaKind.Byte && args[i].getJavaKind() != JavaKind.Byte) {\n    args[i] = JavaConstant.forByte((byte) args[i].asInt());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Byte parameters require Byte constants — the only subword accepted is none (unlike Short which takes Byte)","Restore source kinds after any stack-kind normalization pass","Store replay data with kind tags, not just values"],"tags":["espresso","jvmci","method-invocation","javakind","byte","subword"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}