{"record":{"id":"1d25d0b8c3d32c33","repo":"nathanmarz/storm","slug":"require-input-fields-for-each-aggregator","errorCode":null,"errorMessage":"Require input fields for each aggregator","messagePattern":"Require input fields for each aggregator","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"storm-core/src/jvm/storm/trident/operation/impl/ChainedAggregatorImpl.java","lineNumber":44,"sourceCode":"import storm.trident.tuple.ComboList;\nimport storm.trident.tuple.TridentTuple;\nimport storm.trident.tuple.TridentTupleView;\nimport storm.trident.tuple.TridentTupleView.ProjectionFactory;\n\npublic class ChainedAggregatorImpl implements Aggregator<ChainedResult> {\n    Aggregator[] _aggs;\n    ProjectionFactory[] _inputFactories;\n    ComboList.Factory _fact;\n    Fields[] _inputFields;\n    \n    \n    \n    public ChainedAggregatorImpl(Aggregator[] aggs, Fields[] inputFields, ComboList.Factory fact) {\n        _aggs = aggs;\n        _inputFields = inputFields;\n        _fact = fact;\n        if(_aggs.length!=_inputFields.length) {\n            throw new IllegalArgumentException(\"Require input fields for each aggregator\");\n        }\n    }\n    \n    public void prepare(Map conf, TridentOperationContext context) {\n        _inputFactories = new ProjectionFactory[_inputFields.length];\n        for(int i=0; i<_inputFields.length; i++) {\n            _inputFactories[i] = context.makeProjectionFactory(_inputFields[i]);\n            _aggs[i].prepare(conf, new TridentOperationContext(context, _inputFactories[i]));\n        }\n    }\n    \n    public ChainedResult init(Object batchId, TridentCollector collector) {\n        ChainedResult initted = new ChainedResult(collector, _aggs.length);\n        for(int i=0; i<_aggs.length; i++) {\n            initted.objs[i] = _aggs[i].init(batchId, initted.collectors[i]);\n        }\n        return initted;\n    }","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-core/src/jvm/storm/trident/operation/impl/ChainedAggregatorImpl.java#L26-L62","documentation":"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.","triggerScenarios":"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).","commonSituations":"Low-level direct use of ChainedAggregatorImpl in custom Trident wiring; building custom composite operations and omitting a null/empty entry in the inputFields list.","solutions":["Provide exactly one Fields per aggregator in the inputFields array","Verify both arrays have the same length before constructing (add an assertion in your builder code)","Use ChainedAggregatorDeclarer high-level API instead of assembling ChainedAggregatorImpl manually"],"exampleFix":"// before\nnew ChainedAggregatorImpl(new Aggregator[]{a1, a2}, new Fields[]{f1}, fact);\n// after\nnew ChainedAggregatorImpl(new Aggregator[]{a1, a2}, new Fields[]{f1, f2}, fact);","handlingStrategy":"type-guard","validationCode":"if (aggs.length != inputFields.length) {\n    throw new IllegalArgumentException(\"Need one Fields per aggregator: aggs=\" + aggs.length + \" fields=\" + inputFields.length);\n}","typeGuard":"boolean inputFieldsMatch(Aggregator[] aggs, Fields[] fields) {\n    return aggs != null && fields != null && aggs.length == fields.length;\n}","tryCatchPattern":"try {\n    new ChainedAggregatorImpl(aggs, inputFields, fact);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().equals(\"Require input fields for each aggregator\")) {\n        throw new IllegalStateException(\"inputFields array must parallel aggs array\", e);\n    } throw e;\n}","preventionTips":["Always build aggs and inputFields together in a single loop","Prefer ChainedAggregatorDeclarer over manual ChainedAggregatorImpl construction","Assert equal lengths in custom builder helpers"],"tags":["storm","trident","aggregator","constructor"],"backgroundTag":"missing-required-argument","analyzedSha":"cdb116e942666973bc4eaa0df098d5bab82739e7","analyzedAt":"2026-09-12T14:30:00.714Z","contentChangedAt":"2026-09-12T14:30:00.714Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}