nathanmarz/storm · error · IllegalArgumentException
Combiner aggs only take a single field as input. Got this…
Error message
Combiner aggs only take a single field as input. Got this instead:
What it means
MapCombinerAggStateUpdater applies a CombinerAggregator over grouped state, and CombinerAggregators by contract reduce exactly one input field per tuple. The constructor validates inputFields and throws IllegalArgumentException if more or fewer than one field is supplied.
Solutions
- Pass exactly one field: persistentAggregate(state, new Sum(new Fields("value")), new Fields("sum"))
- If multiple inputs are needed, combine them first with each() into a single field, or use a ReducerAggregator/Aggregator instead
- Ensure the value fields selector excludes group fields
Example fix
// before
.persistentAggregate(state, new Sum(), new Fields("a", "b"), new Fields("sum"))
// after
.persistentAggregate(state, new Sum(new Fields("a")), new Fields("sum")) Defensive patterns
Strategy: validation
Validate before calling
if (inputFields.size() != 1) {
throw new IllegalArgumentException("CombinerAggregator requires exactly one input field, got: " + inputFields);
} Try / catch
try {
stream.persistentAggregate(stateFactory, combinerAgg, valueFields, new Fields("out"));
} catch (IllegalArgumentException e) {
LOG.error("persistentAggregate field count invalid: " + e.getMessage());
} Prevention
- Always pass a single-field Fields to combiner aggregator persistentAggregate calls
- Pre-combine multiple columns via each() into one field
- Prefer ReducerAggregator when multiple fields are genuinely needed
When it happens
Trigger: Calling persistentAggregate with a CombinerAggregator (e.g. Count(), Sum(new Fields("x"))) where the value Fields has size != 1, e.g. new Fields("a","b") or empty fields.
Common situations: Trying to aggregate multiple columns with a combiner agg; passing zero-arg Fields by mistake; converting a ReducerAggregator pipeline to CombinerAggregator without trimming fields.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Output fields for chained aggregators must be distinct
- Unknown field name:
- Additive operations cannot add fields with same name as…
- Fields order must be same length as pointers map
- duplicate field
AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12).
Data as JSON: /api/errors/1e209eba2c686ef1.
Report an issue: GitHub.
Appendix: source
Thrown at storm-core/src/jvm/storm/trident/state/map/MapCombinerAggStateUpdater.java:49
import storm.trident.tuple.ComboList;
import storm.trident.tuple.TridentTuple;
import storm.trident.tuple.TridentTupleView.ProjectionFactory;
public class MapCombinerAggStateUpdater implements StateUpdater<MapState> {
CombinerAggregator _agg;
Fields _groupFields;
Fields _inputFields;
ProjectionFactory _groupFactory;
ProjectionFactory _inputFactory;
ComboList.Factory _factory;
public MapCombinerAggStateUpdater(CombinerAggregator agg, Fields groupFields, Fields inputFields) {
_agg = agg;
_groupFields = groupFields;
_inputFields = inputFields;
if(inputFields.size()!=1) {
throw new IllegalArgumentException("Combiner aggs only take a single field as input. Got this instead: " + inputFields.toString());
}
_factory = new ComboList.Factory(groupFields.size(), inputFields.size());
}
@Override
public void updateState(MapState map, List<TridentTuple> tuples, TridentCollector collector) {
List<List<Object>> groups = new ArrayList<List<Object>>(tuples.size());
List<ValueUpdater> updaters = new ArrayList<ValueUpdater>(tuples.size());
for(TridentTuple t: tuples) {
groups.add(_groupFactory.create(t));
updaters.add(new CombinerValueUpdater(_agg,_inputFactory.create(t).getValue(0)));
}
List<Object> newVals = map.multiUpdate(groups, updaters);
for(int i=0; i<tuples.size(); i++) {
List<Object> key = groups.get(i);View on GitHub (pinned to cdb116e942)