apache/shardingsphere · error · MCPInvalidToolArgumentException

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

Error message

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

What it means

SQLExecutionToolHandlerSupport.getIntegerArgument catches the MCPInvalidRequestException raised by MCPToolArguments.getIntegerArgument for numeric arguments (e.g. max_rows) and rethrows MCPInvalidToolArgumentException: '%s must be an integer between %d and %d.' with the tool name, minimum, and maximum. Bounds for max_rows are 0..MCPRuntimeProtectionPolicy.MAX_ROWS_LIMIT (0 meaning 'use the default'). This validates numeric tool arguments before any SQL is analyzed or executed.

Source

Thrown at mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLExecutionToolHandlerSupport.java:102

        if (database.isEmpty()) {
            return "";
        }
        List<ShardingSphereSchema> schemas = requestContext.getMetadataQueryFacade().querySchemas(database);
        return 1 == schemas.size() ? schemas.iterator().next().getName() : "";
    }
    
    private static int resolveMaxRows(final MCPToolArguments toolArguments, final String sourceTool) {
        int result = getIntegerArgument(toolArguments, sourceTool, "max_rows", MCPRuntimeProtectionPolicy.DEFAULT_MAX_ROWS, 0, MCPRuntimeProtectionPolicy.MAX_ROWS_LIMIT,
                MCPRuntimeProtectionPolicy.DEFAULT_MAX_ROWS);
        return 0 == result ? MCPRuntimeProtectionPolicy.DEFAULT_MAX_ROWS : result;
    }
    
    private static int getIntegerArgument(final MCPToolArguments toolArguments, final String sourceTool, final String argumentPath, final int defaultValue, final int minimumValue,
                                          final int maximumValue, final int suggestedValue) {
        try {
            return toolArguments.getIntegerArgument(argumentPath, defaultValue, minimumValue, maximumValue);
        } catch (final MCPInvalidRequestException ex) {
            throw new MCPInvalidToolArgumentException(sourceTool, sourceTool, argumentPath, minimumValue, maximumValue, suggestedValue, ex);
        }
    }
    
    static void putIfNotEmpty(final Map<String, Object> target, final String key, final String value) {
        if (!value.isEmpty()) {
            target.put(key, value);
        }
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Send max_rows as an integer within [0, MAX_ROWS_LIMIT], or omit it to get the default.
  2. Coerce and clamp client-side before invoking the tool.
  3. If a higher limit is truly needed, have the operator raise MCPRuntimeProtectionPolicy.MAX_ROWS_LIMIT.

Example fix

// before
await tools.call('database_gateway_execute_query', { sql, max_rows: 'all' }); // not an integer -> error

// after
await tools.call('database_gateway_execute_query', { sql, max_rows: 200 });
Defensive patterns

Strategy: validation

Validate before calling

function normalizeMaxRows(raw) {
  const n = Number(raw);
  if (!Number.isInteger(n) || n < 0 || n > MAX_ROWS_LIMIT) {
    return DEFAULT_MAX_ROWS; // omit to use server default, or throw early with a clear message
  }
  return n;
}
const args = { sql };
const maxRows = normalizeMaxRows(userMaxRows);
if (maxRows !== DEFAULT_MAX_ROWS) args.max_rows = maxRows;

Type guard

function isValidMaxRows(value) {
  return Number.isInteger(value) && value >= 0 && value <= MAX_ROWS_LIMIT;
}

Try / catch

try {
  return await tools.call('database_gateway_execute_query', { sql, max_rows });
} catch (e) {
  if (/must be an integer between/.test(e.message)) {
    const [, min, max] = e.message.match(/between (\d+) and (\d+)/) ?? [];
    return tools.call('database_gateway_execute_query', { sql, max_rows: Math.min(Math.max(0, max_rows|0), Number(max)) });
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing max_rows (or another numeric argument) as a non-integer (string like 'all', float), an integer below the minimum, or above the configured MAX_ROWS_LIMIT.

Common situations: LLM emitting "max_rows": "100" as a string or "max_rows": 1000000 exceeding the cap; UI default of -1; JSON coercion surprises where numbers arrive as strings.

Related errors


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