spring-projects/spring-ai · error · java.lang.IllegalArgumentException

Cannot safely convert numeric value '{value}' to int

Error message

Cannot safely convert numeric value '{value}' to int

What it means

When binding prompt arguments to an int/Integer parameter, convertArgumentValue delegates to toIntegerExact, which converts the Number via BigDecimal.intValueExact(). If the value is fractional, out of int range, or unrepresentable, intValueExact throws ArithmeticException (or NumberFormatException), rethrown as this IllegalArgumentException. The library refuses lossy conversions rather than silently truncating.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/AbstractMcpPromptMethodCallback.java:338

		else if (targetType == Boolean.class || targetType == boolean.class) {
			if (value instanceof Boolean) {
				return value;
			}
			else {
				return Boolean.parseBoolean(value.toString());
			}
		}

		// For other types, return as is and hope for the best
		return value;
	}

	private int toIntegerExact(Number value) {
		try {
			return this.toBigDecimal(value).intValueExact();
		}
		catch (ArithmeticException | NumberFormatException ex) {
			throw new IllegalArgumentException("Cannot safely convert numeric value '" + value + "' to int", ex);
		}
	}

	private long toLongExact(Number value) {
		try {
			return this.toBigDecimal(value).longValueExact();
		}
		catch (ArithmeticException | NumberFormatException ex) {
			throw new IllegalArgumentException("Cannot safely convert numeric value '" + value + "' to long", ex);
		}
	}

	private BigDecimal toBigDecimal(Number value) {
		if (value instanceof BigDecimal bigDecimal) {
			return bigDecimal;
		}
		if (value instanceof BigInteger bigInteger) {
			return new BigDecimal(bigInteger);

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Change the parameter type to long or double if the value can legitimately be larger or fractional.
  2. Validate/coerce the incoming argument client-side (or in a wrapper method) before it reaches the handler.
  3. Catch IllegalArgumentException around the callback invocation and return a descriptive MCP error to the client asking for an integer in range.

Example fix

// before
@McpArg int maxResults
// after
@McpArg long maxResults  // or validate: if (d != Math.floor(d) || d > Integer.MAX_VALUE) throw ...
Defensive patterns

Strategy: try-catch

Validate before calling

boolean safeAsInt(Number n) {
    try { return new BigDecimal(n.toString()).intValueExact() >= 0; }
    catch (ArithmeticException | NumberFormatException e) { return false; }
}

Type guard

boolean isExactInt(Object v) {
    return v instanceof Number n
        && new BigDecimal(n.toString()).scale() <= 0
        && new BigDecimal(n.toString()).compareTo(BigDecimal.valueOf(Integer.MAX_VALUE)) <= 0
        && new BigDecimal(n.toString()).compareTo(BigDecimal.valueOf(Integer.MIN_VALUE)) >= 0;
}

Try / catch

try {
    Object result = callback.apply(exchange, request);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Cannot safely convert numeric value")) {
        return errorResponse("Argument must be an integer within int range");
    }
    throw e;
}

Prevention

When it happens

Trigger: A client sends a prompt argument like 3.5, 1e30, or 2147483648 for a method parameter typed int/Integer with @McpArg; buildArgs -> convertArgumentValue -> toIntegerExact throws at invocation time.

Common situations: LLM clients emitting float-typed numbers for integer fields (JSON 3.0 vs 3); client sending a count/limit exceeding Integer.MAX_VALUE; decimal input like 0.5 for an int parameter.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/4552cc7a05e6f6a1. Report an issue: GitHub.