github/copilot-sdk · error · IllegalArgumentException
Parameter ' + param.name() + ' expected a numeric value for…
Error message
Parameter ' + param.name() + ' expected a numeric value for OptionalLong, got: + raw.getClass().getSimpleName()
What it means
Thrown by ParamCoercion.coerce when an RPC parameter declared as java.util.OptionalLong receives a value that is not a java.lang.Number. The coercion attempts ((Number) raw).longValue() and wraps the resulting ClassCastException into an IllegalArgumentException naming the parameter and the offending runtime class. This guards tool parameters that require an integral numeric value (possibly absent).
Solutions
- Pass a java.lang.Number (Long/Integer/BigInteger) for OptionalLong parameters, or omit the key / pass null for empty Optional
- Convert string inputs first: OptionalLong.of(Long.parseLong(String.valueOf(raw))) before invoking the tool
- Check the tool schema (ParamSchema.buildSchema) for the parameter's declared type and match it in the client payload
- Catch IllegalArgumentException around the tool invocation and log param.name() plus raw.getClass() to fix the caller
Example fix
// before
Map<String,Object> args = Map.of("count", "42");
tool.invoke(args); // throws: expected a numeric value for OptionalLong, got: String
// after
Map<String,Object> args = Map.of("count", 42L);
tool.invoke(args); Defensive patterns
Strategy: type-guard
Validate before calling
if (raw instanceof Number) { args.put("count", ((Number) raw).longValue()); } Type guard
boolean isNumber(Object v) { return v instanceof Number; } Try / catch
try { tool.invoke(args); } catch (IllegalArgumentException e) { if (e.getMessage().contains("OptionalLong")) { /* convert string to Long and retry */ } else { throw e; } } Prevention
- Match JSON types exactly to the declared parameter type (unquoted numbers)
- Coerce string inputs to Long before invoking tools
- Validate payloads against the tool's generated schema
When it happens
Trigger: Calling a tool whose @Param is OptionalLong and passing a raw value whose runtime class is not a Number — e.g. a String like "42", a Boolean, or a Map/List (typically from deserialized JSON that was not pre-typed).
Common situations: Clients send long parameters as JSON strings; a caller builds argument maps by hand and puts String instead of Long; a JSON binder leaves numbers as String or BigInteger-derived types when config disables numeric typing.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Parameter ' + param.name() + ' expected a numeric value for…
- Parameter ' + param.name() + ' expected a numeric value for…
- Unknown AgentMode value: + value
- Unknown AskUserVariant value: + value
- Unknown AutoTier value: + value
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/7e6a4f512c9c94a4.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/rpc/ParamCoercion.java:90
}
}
Class<T> type = param.type();
// Handle Optional* types explicitly before delegating to ObjectMapper
if (type == java.util.OptionalInt.class) {
try {
return (T) java.util.OptionalInt.of(((Number) raw).intValue());
} catch (ClassCastException ex) {
throw new IllegalArgumentException("Parameter '" + param.name()
+ "' expected a numeric value for OptionalInt, got: " + raw.getClass().getSimpleName(), ex);
}
}
if (type == java.util.OptionalLong.class) {
try {
return (T) java.util.OptionalLong.of(((Number) raw).longValue());
} catch (ClassCastException ex) {
throw new IllegalArgumentException("Parameter '" + param.name()
+ "' expected a numeric value for OptionalLong, got: " + raw.getClass().getSimpleName(), ex);
}
}
if (type == java.util.OptionalDouble.class) {
try {
return (T) java.util.OptionalDouble.of(((Number) raw).doubleValue());
} catch (ClassCastException ex) {
throw new IllegalArgumentException("Parameter '" + param.name()
+ "' expected a numeric value for OptionalDouble, got: " + raw.getClass().getSimpleName(), ex);
}
}
try {
return mapper.convertValue(raw, type);
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException(
"Failed to coerce parameter '" + param.name() + "' to type " + type.getSimpleName(), ex);
}View on GitHub (pinned to cd8cf15dc3)