redis/jedis · error · UnsupportedAggregationException
AGG_SUM policy requires numeric type, but got
Error message
AGG_SUM policy requires numeric type, but got: ${newReply.getClass().getName()} What it means
ClusterReplyAggregator combines replies broadcast to multiple shards. For the AGG_SUM response policy it requires every reply to be numeric (Long/Double); when the first non-null reply is any other type it throws UnsupportedAggregationException naming the offending type. The delegate aggregator is lazily initialized from the first reply, so a non-numeric first reply fails immediately.
Solutions
- Only apply the AGG_SUM policy to commands guaranteed to return numeric replies on all shards.
- Pre-validate the values stored in the targeted keys are integers/floats before broadcasting increment commands.
- Switch the response policy to one matching the actual reply type (e.g. DEFAULT or FIRST) in the command definition.
- Handle shard errors before aggregation so error replies aren't fed into the AGG_SUM aggregator.
Example fix
// before
CommandObject<Long> obj = new CommandObject<>(args(FLUSHDB).responsePolicy(ResponsePolicy.AGG_SUM), BuilderFactory.LONG);
// after
CommandObject<Long> obj = new CommandObject<>(args(INCRBY).key(key)
.responsePolicy(ResponsePolicy.AGG_SUM), BuilderFactory.LONG); Defensive patterns
Strategy: validation
Validate before calling
// ensure target keys hold numeric values before an AGG_SUM broadcast
Object v = jedis.get(key);
if (v != null && !v.toString().matches("-?\\d+(\\.\\d+)?")) {
throw new IllegalStateException("key " + key + " is not numeric; AGG_SUM would fail");
} Type guard
boolean isNumericReply(Object reply) { return reply instanceof Number; } Try / catch
try {
return broadcastSum();
} catch (UnsupportedAggregationException e) {
logger.error("non-numeric reply under AGG_SUM: {}", e.getMessage());
throw new IllegalStateException(e);
} Prevention
- Attach AGG_SUM only to commands returning numbers on every shard
- Store only numeric data in keys aggregated with AGG_SUM
- Convert shard error replies before aggregation
- Document response policies with each custom command
When it happens
Trigger: Broadcasting commands with an AGG_SUM response policy where shards return non-numeric values — e.g. INCRBY on keys that hold non-integer strings returning an error reply/object, or a command whose builder attached AGG_SUM but returns strings/nulls.
Common situations: Aggregating INCR/INCRBY across cluster shards where some keys hold non-numeric values; misuse of the response-policy API wrapping commands that return strings (GET) with AGG_SUM; a shard returning an error object instead of a number.
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
- DEFAULT policy requires List, Set, Map, JedisByteHashMap…
- requires Boolean, Long, ArrayList , or ArrayList , but got
- Broadcast command is only supported in…
- commandObjects must not be null or empty
- requires Boolean, Long, ArrayList , or ArrayList , but got…
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/b658e31b9a07a41f.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/executors/aggregators/ClusterReplyAggregator.java:37
this.policy = Objects.requireNonNull(policy, "policy cannot be null");
}
/**
* Adds a new value to the aggregator. Null values are ignored.
*/
@Override
@SuppressWarnings("unchecked")
public void add(T newReply) {
if (newReply == null) {
return; // ignore nulls
}
// Lazy initialization of delegate based on policy and first non-null value
if (delegate == null) {
switch (policy) {
case AGG_SUM:
if (!(newReply instanceof Number)) {
throw new UnsupportedAggregationException(
"AGG_SUM policy requires numeric type, but got: " + newReply.getClass().getName());
}
delegate = (Aggregator<T, T>) new SumAggregator<>(); // safe cast
break;
case AGG_MIN:
delegate = new MinAggregator<>();
break;
case AGG_MAX:
delegate = new MaxAggregator<>();
break;
case AGG_LOGICAL_AND:
delegate = new LogicalAndAggregator<>();
break;
case AGG_LOGICAL_OR:
delegate = new LogicalOrAggregator<>();
break;
case DEFAULT:
delegate = new DefaultPolicyAggregator<>();View on GitHub (pinned to 6dac31d4c2)