apache/shardingsphere · error · MCPInvalidRequestException

%s must be an integer between %d and %d.

Error message

%s must be an integer between %d and %d.

What it means

Thrown by MCPToolArguments.getIntegerArgument (MCPInvalidRequestException) when a numeric argument parses as an integer but falls outside the tool's accepted [minValue, maxValue] range. The message names the argument and the exact accepted bounds, e.g. "limit must be an integer between 1 and 1000.".

Source

Thrown at mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/request/MCPToolArguments.java:112

    public String getStringArgument(final String name) {
        return Objects.toString(arguments.get(name), "").trim();
    }
    
    /**
     * Get bounded integer argument.
     *
     * @param name argument name
     * @param defaultValue default value
     * @param minValue minimum accepted value
     * @param maxValue maximum accepted value
     * @return argument value
     * @throws MCPInvalidRequestException when value is not an integer or is outside the accepted range
     */
    public int getIntegerArgument(final String name, final int defaultValue, final int minValue, final int maxValue) {
        Object value = arguments.get(name);
        int result = parseIntegerArgument(name, value, defaultValue);
        if (result < minValue || result > maxValue) {
            throw new MCPInvalidRequestException(String.format("%s must be an integer between %d and %d.", name, minValue, maxValue));
        }
        return result;
    }
    
    private int parseIntegerArgument(final String name, final Object value, final int defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        String actualValue = Objects.toString(value, "").trim();
        if (actualValue.isEmpty()) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(actualValue);
        } catch (final NumberFormatException ex) {
            throw new MCPInvalidRequestException(String.format("%s must be an integer.", name), ex);
        }
    }

View on GitHub (pinned to e952770a21)

Solutions

  1. Clamp the value into the range reported in the message before retrying (e.g. limit to the documented max, then paginate)
  2. Omit the argument entirely to accept the tool default when you do not need a specific value
  3. Cache each tool's declared min/max from its descriptor and validate client-side

Example fix

// before
query({"sql": "...", "limit": 100000})

// after
query({"sql": "...", "limit": 1000}) -- and paginate with offset if more rows needed
Defensive patterns

Strategy: validation

Validate before calling

// Clamp numeric args to the tool's declared range before sending
int v = Integer.parseInt(String.valueOf(arguments.get("limit")));
if (v < LIMIT_MIN || v > LIMIT_MAX) arguments.put("limit", Math.max(LIMIT_MIN, Math.min(LIMIT_MAX, v)));

Type guard

const inRange = (v: unknown, min: number, max: number): v is number =>
  typeof v === "number" && Number.isInteger(v) && v >= min && v <= max;

Try / catch

try {
    query(arguments);
} catch (MCPInvalidRequestException e) {
    Matcher m = Pattern.compile("(\\w+) must be an integer between (-?\\d+) and (-?\\d+)").matcher(e.getMessage());
    if (m.find()) { arguments.put(m.group(1), Integer.parseInt(m.group(3))); return query(arguments); }
    throw e;
}

Prevention

When it happens

Trigger: getIntegerArgument(name, default, min, max) with a present, non-blank value whose parse succeeds but result < min or > max — e.g. limit=0, limit=10000, timeout=-1. Null or blank values fall back to the default and do NOT throw; only out-of-range explicit values do.

Common situations: Agents setting limit=1000000 to 'fetch everything'; copying defaults between tools whose ranges differ (pagination limit vs timeout); negative values from arithmetic on unset variables in client code.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/7d786e6388143862. Report an issue: GitHub.