{"record":{"id":"4d95eddd84b6e966","repo":"oracle/graal","slug":"bad-argument-kind-at-index-expected-boolean-g","errorCode":null,"errorMessage":"Bad argument kind at index {}: expected Boolean, got {}","messagePattern":"Bad argument kind at index (.+?): expected Boolean, 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":323,"sourceCode":"        } else if (!isStatic()) {\n            if (!(receiver instanceof EspressoExternalObjectConstant objectConstant)) {\n                throw new IllegalArgumentException(\"Bad receiver: expected Object, got \" + arguments[0].getJavaKind());\n            }\n            args[0] = objectConstant.getValue();\n            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();","sourceCodeStart":305,"sourceCodeEnd":341,"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#L305-L341","documentation":"Thrown by EspressoExternalResolvedJavaMethod.invoke's argument marshalling switch when a parameter is declared boolean but the supplied JavaConstant's JavaKind is not Boolean. Unlike the numeric kinds, boolean is not part of JVMCI's widening lattice (booleans are not widened to int in strict invocation, JLS 5.3), so the adapter accepts only an exact Boolean constant and rejects anything else with the parameter index and actual kind in the message.","triggerScenarios":"Passing JavaConstant.forInt(0/1), a boxed Boolean wrapped in the wrong constant type, or an Int-kind constant (common because JVMCI promotes subword kinds) to a boolean parameter at the reported index.","commonSituations":"Constants normalized to Int kind by earlier pipeline stages (stack-kind promotion), replay files that encode booleans as integers, language bridges mapping truthy values to ints.","solutions":["Convert to JavaConstant.forBoolean(...) at the boundary: check signature.getParameterKind(i)==Boolean and box accordingly","Keep a kind-conversion table mirroring the adapter's switch (Boolean accepts only Boolean) instead of assuming numeric coercion","Fix the producer that promoted the boolean constant to Int"],"exampleFix":"// before\nargs[i] = JavaConstant.forInt(flag ? 1 : 0);\nmethod.invoke(receiver, args);\n\n// after\nargs[i] = JavaConstant.forBoolean(flag);\nmethod.invoke(receiver, args);","handlingStrategy":"validation","validationCode":"if (signature.getParameterKind(i) == JavaKind.Boolean && args[i].getJavaKind() != JavaKind.Boolean) {\n    args[i] = JavaConstant.forBoolean(args[i].asInt() != 0);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Booleans are never coerced here: only exact Boolean constants are accepted","Watch for Int-kind constants that were subword-promoted earlier in the pipeline","Centralize argument adaptation in a converter mirroring the adapter's switch"],"tags":["espresso","jvmci","method-invocation","javakind","boolean","argument-marshalling"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}