apache/shardingsphere · error · IllegalArgumentException
SQL federation pagination parameter value `%s` must be an in
Error message
SQL federation pagination parameter value `%s` must be an integer.
What it means
StandardSQLFederationProcessor validates LIMIT/OFFSET pagination parameter values for federated execution. A Number parameter whose decimal form is not exactly an integer (e.g. 1.5, or a double with fraction) fails BigDecimal.toBigIntegerExact() and throws IllegalArgumentException stating the value must be an integer. A separate sibling check enforces the 0..Integer.MAX_VALUE range.
Source
Thrown at kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/engine/processor/impl/StandardSQLFederationProcessor.java:191
paginationContext.getOffsetParameterIndex().ifPresent(result::add);
paginationContext.getRowCountParameterIndex().ifPresent(result::add);
}
private Object convertPaginationParameter(final Object value) {
if (!(value instanceof Number)) {
return value;
}
BigInteger integerValue = getIntegerValue((Number) value);
ShardingSpherePreconditions.checkState(integerValue.compareTo(MIN_PAGINATION_PARAMETER) >= 0 && integerValue.compareTo(MAX_PAGINATION_PARAMETER) <= 0,
() -> new IllegalArgumentException(String.format("SQL federation pagination parameter value `%s` is out of integer range.", value)));
return integerValue.intValue();
}
private BigInteger getIntegerValue(final Number value) {
try {
return new BigDecimal(value.toString()).toBigIntegerExact();
} catch (final NumberFormatException | ArithmeticException ex) {
throw new IllegalArgumentException(String.format("SQL federation pagination parameter value `%s` must be an integer.", value), ex);
}
}
@Override
public Convention getConvention() {
return EnumerableConvention.INSTANCE;
}
}
View on GitHub (pinned to e952770a21)
Solutions
- Bind integral types for LIMIT/OFFSET parameters (setInt/setLong), or round/truncate to whole numbers before binding.
- Validate computed pagination values in application code before executing the query.
- If a decimal like 10.0 arrives as Double, normalize it: BigDecimal.valueOf(d).setScale(0, RoundingMode.DOWN) when the semantic is a whole count.
Example fix
// before ps.setObject(1, pageSizePercent * total / 100.0); // may be 7.5 // after int limit = (int) Math.floor(pageSizePercent * total / 100.0); ps.setInt(1, limit);
Defensive patterns
Strategy: validation
Validate before calling
static int paginationParam(Object v) {
if (!(v instanceof Number)) throw new IllegalArgumentException("pagination param must be Number");
BigInteger i = new BigDecimal(v.toString()).toBigIntegerExact(); // throws early, clearly
if (i.signum() < 0 || i.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
throw new IllegalArgumentException("pagination param out of range: " + v);
}
return i.intValue();
}
// call paginationParam(limit) before ps.setXxx(...) and before executing federated query Try / catch
try {
rs = stmt.executeQuery();
} catch (final IllegalArgumentException ex) {
if (ex.getMessage().contains("must be an integer")) { fixPaginationAndRetry(); } else { throw ex; }
} Prevention
- Always bind LIMIT/OFFSET with setInt/setLong.
- Never bind computed fractional values directly.
- Centralize pagination parameter validation in one helper.
When it happens
Trigger: Binding a non-integral Number (float/double/BigDecimal with fraction) as a LIMIT or OFFSET parameter of a federated query; getIntegerValue is called from pagination parameter conversion during plan execution.
Common situations: Applications computing LIMIT dynamically (page size division, percentages) producing fractional values; passing Double parameters through PreparedStatement.setObject; upstream data producing 10.0-style decimals that carry fractions elsewhere.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/d332254b3eb9693f.
Report an issue: GitHub.