{"record":{"id":"ae78624292838dbb","repo":"oracle/graal","slug":"bad-argument-kind-at-index-expected-double-go","errorCode":null,"errorMessage":"Bad argument kind at index {}: expected Double, got {}","messagePattern":"Bad argument kind at index (.+?): expected Double, 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":361,"sourceCode":"                        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) {\n                    case Long, Int, Char, Short, Byte -> (double) argument.asLong();\n                    case Float -> (double) argument.asFloat();\n                    case Double -> argument.asDouble();\n                    default ->\n                        throw new IllegalArgumentException(\"Bad argument kind at index \" + i + \": expected Double, got \" + argumentKind);\n                };\n                case Object -> {\n                    if (argument.isNull()) {\n                        yield null;\n                    }\n                    if (!(argument instanceof EspressoExternalObjectConstant objectConstant)) {\n                        throw new IllegalArgumentException(\n                                        \"Bad argument kind at index \" + i + \": expected Object, got \" + argumentKind + \" wrapped in a \" + argument.getClass().getName());\n                    }\n                    yield objectConstant.getValue();\n                }\n                default -> JVMCIError.shouldNotReachHere(signature.getParameterKind(i).toString());\n            };\n        }\n        Value result;\n        try {\n            result = vmMethodMirror.execute(args);\n        } catch (PolyglotException e) {","sourceCodeStart":343,"sourceCodeEnd":379,"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#L343-L379","documentation":"Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared double but the argument constant's kind is not in {Long, Int, Char, Short, Byte, Float, Double}. This is the widest numeric acceptance set (everything numeric widens to double, JLS 5.1.2); only Boolean and Object constants are rejected, since neither is convertible to double under strict invocation. Hitting it usually means an argument order problem or a wrong method resolved rather than a genuine conversion gap.","triggerScenarios":"Passing a Boolean constant to a double parameter; passing an EspressoExternalObjectConstant (object) where a double is declared; argument array shifted by including the receiver or dropping an argument.","commonSituations":"Off-by-one argument alignment after adapting from java.lang.reflect.Method.invoke; resolving an overload with a different signature than intended; polymorphic call sites mis-dispatched.","solutions":["Recheck argument alignment: receiver excluded, arity equals getParameterCount(false), each constant matches its parameter position","Verify the resolved ResolvedJavaMethod is the intended overload (compare name and signature)","Convert Boolean constants to a numeric double explicitly if the guest API really takes double for a truth flag"],"exampleFix":"// before: receiver accidentally left in args\nJavaConstant[] args = {receiver, JavaConstant.forDouble(x)};\nmethod.invoke(null, args); // instance method -> misaligned\n\n// after\nJavaConstant[] args = {JavaConstant.forDouble(x)};\nmethod.invoke(receiver, args);","handlingStrategy":"validation","validationCode":"JavaKind ak = args[i].getJavaKind();\nboolean numeric = ak == JavaKind.Double || ak == JavaKind.Float || ak == JavaKind.Long || ak == JavaKind.Int || ak == JavaKind.Char || ak == JavaKind.Short || ak == JavaKind.Byte;\nif (signature.getParameterKind(i) == JavaKind.Double && !numeric) {\n    throw new IllegalStateException(\"argument \" + i + \" not numeric for double parameter\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Double accepts every numeric kind; Boolean/Object rejections almost always indicate misaligned arguments","Check receiver exclusion and arity whenever this fires","Verify overload resolution when a method has boxed/unboxed variants"],"tags":["espresso","jvmci","method-invocation","javakind","double","argument-alignment"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}