{"record":{"id":"305a7d8c29fdbf70","repo":"oracle/graal","slug":"bad-argument-kind-at-index-expected-float-got","errorCode":null,"errorMessage":"Bad argument kind at index {}: expected Float, got {}","messagePattern":"Bad argument kind at index (.+?): expected Float, 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":354,"sourceCode":"                    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) {\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                }","sourceCodeStart":336,"sourceCodeEnd":372,"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#L336-L372","documentation":"Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared float but the argument constant's kind is not in {Long, Int, Char, Short, Byte, Float}. Integral constants are widened and cast to float ((float) asLong()); Double is rejected because double-to-float is a narrowing conversion (JLS 5.1.3) not permitted by strict invocation, and Boolean/Object are invalid. Note the integral path goes through long, which is lossy for large ints converted to float — but that matches JVM widening semantics for byte/char/short/int-to-float via long representation.","triggerScenarios":"Passing JavaConstant.forDouble(...) to a float parameter; passing a Boolean or object constant; constants produced by generic double-based number bridges.","commonSituations":"Interop from languages with only doubles (JS, Python) where every number is a Double constant; parameter type changed from double to float in a guest class version; misaligned argument arrays.","solutions":["Narrow explicitly when intended: JavaConstant.forFloat((float) d.asDouble())","For bridges that only produce doubles, insert a kind-conversion step driven by signature.getParameterKind(i)","Confirm the argument index alignment if the kind reported makes no sense for that parameter"],"exampleFix":"// before\nargs[i] = JavaConstant.forDouble(ratio); // parameter is float\n\n// after\nargs[i] = JavaConstant.forFloat((float) ratio);","handlingStrategy":"validation","validationCode":"if (signature.getParameterKind(i) == JavaKind.Float && args[i].getJavaKind() == JavaKind.Double) {\n    args[i] = JavaConstant.forFloat((float) args[i].asDouble());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Double is never implicitly narrowed to float — cast and rebox explicitly","Bridges from double-only languages must convert per-parameter using the signature","Integral constants are accepted and converted via long, matching JVM widening"],"tags":["espresso","jvmci","method-invocation","javakind","float","narrowing"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}