github/copilot-sdk · error · IllegalArgumentException

Parameter ' + param.name() + ' expected a numeric value for…

Error message

Parameter ' + param.name() + ' expected a numeric value for OptionalDouble, got: + raw.getClass().getSimpleName()

What it means

Thrown by ParamCoercion.coerce when an RPC parameter declared as java.util.OptionalDouble receives a value that is not a java.lang.Number. The coercion attempts ((Number) raw).doubleValue() and wraps the ClassCastException into an IllegalArgumentException naming the parameter and the actual runtime class.

Solutions

  1. Pass a java.lang.Number (Double/BigDecimal) for OptionalDouble parameters, or null/omit for empty
  2. Convert strings first: OptionalDouble.of(Double.parseDouble(String.valueOf(raw)))
  3. Verify the tool parameter schema and send properly typed JSON numbers (unquoted)
  4. Catch IllegalArgumentException, inspect the parameter name and runtime class reported in the message, and fix the payload

Example fix

// before
args.put("rate", "0.25"); // String
tool.invoke(args); // throws: expected a numeric value for OptionalDouble, got: String
// after
args.put("rate", 0.25d);
tool.invoke(args);
Defensive patterns

Strategy: type-guard

Validate before calling

if (raw instanceof Number) { args.put("rate", ((Number) raw).doubleValue()); }

Type guard

boolean isNumber(Object v) { return v instanceof Number; }

Try / catch

try { tool.invoke(args); } catch (IllegalArgumentException e) { if (e.getMessage().contains("OptionalDouble")) { /* convert to Double and retry */ } else { throw e; } }

Prevention

When it happens

Trigger: Calling a tool with an OptionalDouble parameter but supplying a String (e.g. "3.14"), Boolean, or collection — typically from hand-built argument maps or lenient JSON deserialization.

Common situations: Numeric values passed as JSON strings; config files quoting numbers; clients using a different locale/format ("3,14") or sending integers-as-strings.

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


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/3d4b60f8a41c00f2. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/rpc/ParamCoercion.java:98

                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);
        }
    }

    /**
     * Parses a {@link Param}'s string default value into the declared Java type.
     *
     * <p>
     * Handles primitives, boxed types, {@link String}, {@link Boolean}, and enums
     * explicitly, mirroring the validation logic in {@link Param}. The

View on GitHub (pinned to cd8cf15dc3)