oracle/graal · error · IllegalArgumentException
Bad argument kind at index
Error message
Bad argument kind at index {}: expected Long, got {} What it means
Thrown by the argument marshalling switch in EspressoExternalResolvedJavaMethod.invoke when a parameter is declared long but the argument constant's kind is not in {Long, Int, Char, Short, Byte}. All subword integral kinds widen to long (JLS 5.1.2); Float, Double, Boolean, and Object constants are rejected because converting them to long is either lossy or invalid under strict invocation. The index in the message identifies which parameter mismatches.
Solutions
- Convert explicitly when narrowing from double: JavaConstant.forLong((long) d.asDouble())
- Verify the argument array is aligned to getSignature().getParameterCount(false) with no receiver included
- If a Float constant is intended for a long parameter, rebox via forLong(argument.asLong()-compatible path) after explicit cast
Example fix
// before args[i] = JavaConstant.forDouble(seconds); // parameter is long // after args[i] = JavaConstant.forLong((long) seconds);
Defensive patterns
Strategy: validation
Validate before calling
JavaKind ak = args[i].getJavaKind();
if (signature.getParameterKind(i) == JavaKind.Long && !(ak == JavaKind.Long || ak == JavaKind.Int || ak == JavaKind.Char || ak == JavaKind.Short || ak == JavaKind.Byte)) {
throw new IllegalStateException("argument " + i + " cannot widen to long; got " + ak);
} Prevention
- All integral subwords widen to long automatically; floating-point does not
- Double-to-long requires an explicit cast and forLong
- An Object constant at a long slot means the argument array is shifted — verify alignment
When it happens
Trigger: Passing JavaConstant.forDouble/forFloat to a long parameter; passing a Boolean constant; passing an EspressoExternalObjectConstant where a long is declared (argument order shifted).
Common situations: Argument array misalignment (extra/missing element earlier shifts an Object into a long slot); signature drift between guest class versions; interop bridges that represent all numbers as doubles.
Related errors
- Bad argument kind at index
- Bad argument kind at index
- Bad argument kind at index
- Bad argument kind at index
- Bad argument kind at index
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/17493e955f17e40b.
Report an issue: GitHub.
Appendix: source
Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaMethod.java:348
case Char -> switch (argumentKind) {
case Char -> argument.asInt();
default ->
throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Char, got " + argumentKind);
};
case Short -> switch (argumentKind) {
case Short, Byte -> argument.asInt();
default ->
throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Short, got " + argumentKind);
};
case Int -> switch (argumentKind) {
case Int, Char, Short, Byte -> argument.asInt();
default ->
throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Int, got " + argumentKind);
};
case Long -> switch (argumentKind) {
case Long, Int, Char, Short, Byte -> argument.asLong();
default ->
throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Long, got " + argumentKind);
};
case Float -> switch (argumentKind) {
case Long, Int, Char, Short, Byte -> (float) argument.asLong();
case Float -> argument.asFloat();
default ->
throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Float, got " + argumentKind);
};
case Double -> switch (argumentKind) {
case Long, Int, Char, Short, Byte -> (double) argument.asLong();
case Float -> (double) argument.asFloat();
case Double -> argument.asDouble();
default ->
throw new IllegalArgumentException("Bad argument kind at index " + i + ": expected Double, got " + argumentKind);
};
case Object -> {
if (argument.isNull()) {
yield null;
}View on GitHub (pinned to a66e9ccd1d)