nathanmarz/storm · error · IllegalArgumentException

Require input fields for each aggregator

Error message

Require input fields for each aggregator

What it means

ChainedAggregatorImpl combines N aggregators and needs one Fields input spec per aggregator so each can build its ProjectionFactory. If the aggs array and inputFields array lengths differ, the constructor throws this IllegalArgumentException immediately.

Solutions

  1. Provide exactly one Fields per aggregator in the inputFields array
  2. Verify both arrays have the same length before constructing (add an assertion in your builder code)
  3. Use ChainedAggregatorDeclarer high-level API instead of assembling ChainedAggregatorImpl manually

Example fix

// before
new ChainedAggregatorImpl(new Aggregator[]{a1, a2}, new Fields[]{f1}, fact);
// after
new ChainedAggregatorImpl(new Aggregator[]{a1, a2}, new Fields[]{f1, f2}, fact);
Defensive patterns

Strategy: type-guard

Validate before calling

if (aggs.length != inputFields.length) {
    throw new IllegalArgumentException("Need one Fields per aggregator: aggs=" + aggs.length + " fields=" + inputFields.length);
}

Type guard

boolean inputFieldsMatch(Aggregator[] aggs, Fields[] fields) {
    return aggs != null && fields != null && aggs.length == fields.length;
}

Try / catch

try {
    new ChainedAggregatorImpl(aggs, inputFields, fact);
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("Require input fields for each aggregator")) {
        throw new IllegalStateException("inputFields array must parallel aggs array", e);
    } throw e;
}

Prevention

When it happens

Trigger: Constructing ChainedAggregatorImpl directly, or via chained agg declarer paths, passing an Aggregator[] and Fields[] of different lengths (e.g. forgetting input fields for one aggregator).

Common situations: Low-level direct use of ChainedAggregatorImpl in custom Trident wiring; building custom composite operations and omitting a null/empty entry in the inputFields list.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12). Data as JSON: /api/errors/1d25d0b8c3d32c33. Report an issue: GitHub.

Appendix: source

Thrown at storm-core/src/jvm/storm/trident/operation/impl/ChainedAggregatorImpl.java:44

import storm.trident.tuple.ComboList;
import storm.trident.tuple.TridentTuple;
import storm.trident.tuple.TridentTupleView;
import storm.trident.tuple.TridentTupleView.ProjectionFactory;

public class ChainedAggregatorImpl implements Aggregator<ChainedResult> {
    Aggregator[] _aggs;
    ProjectionFactory[] _inputFactories;
    ComboList.Factory _fact;
    Fields[] _inputFields;
    
    
    
    public ChainedAggregatorImpl(Aggregator[] aggs, Fields[] inputFields, ComboList.Factory fact) {
        _aggs = aggs;
        _inputFields = inputFields;
        _fact = fact;
        if(_aggs.length!=_inputFields.length) {
            throw new IllegalArgumentException("Require input fields for each aggregator");
        }
    }
    
    public void prepare(Map conf, TridentOperationContext context) {
        _inputFactories = new ProjectionFactory[_inputFields.length];
        for(int i=0; i<_inputFields.length; i++) {
            _inputFactories[i] = context.makeProjectionFactory(_inputFields[i]);
            _aggs[i].prepare(conf, new TridentOperationContext(context, _inputFactories[i]));
        }
    }
    
    public ChainedResult init(Object batchId, TridentCollector collector) {
        ChainedResult initted = new ChainedResult(collector, _aggs.length);
        for(int i=0; i<_aggs.length; i++) {
            initted.objs[i] = _aggs[i].init(batchId, initted.collectors[i]);
        }
        return initted;
    }

View on GitHub (pinned to cdb116e942)