nathanmarz/storm · error · IllegalArgumentException
Additive operations cannot add fields with same name as…
Error message
Additive operations cannot add fields with same name as already exists. Tried adding
What it means
Trident's additive operations (each/newValues) produce a new tuple view whose fields are parent fields plus new fields. Duplicate names between the parent's output fields and the operation's added fields would create ambiguity, so OperationOutputFactory throws IllegalArgumentException.
Solutions
- Rename the newly added fields, e.g. new Fields("x_copy"), or use each with a different output name
- Use a projection (new Fields(...)) to drop conflicting parent fields before the operation
- Ensure custom Functions emit distinct output field names
Example fix
// before
stream.each(new Fields("url"), new Parse(), new Fields("url"))
// after
stream.each(new Fields("url"), new Parse(), new Fields("parsedUrl")) Defensive patterns
Strategy: validation
Validate before calling
Set<String> parent = new HashSet<>(stream.getOutputFields());
for (String f : newFields) {
if (parent.contains(f)) throw new IllegalArgumentException("Field " + f + " already exists on stream");
} Try / catch
try {
stream.each(inputFields, func, outputFields);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Additive operations cannot add fields")) {
LOG.error("Duplicate output field: rename the added fields", e);
}
throw e;
} Prevention
- Name operation outputs distinctly from input fields (e.g. prefixed)
- Check stream.getOutputFields() before wiring each()
- Avoid merging streams with overlapping field names without projection
When it happens
Trigger: An each() (or similar additive operation) declares output fields that already exist on the incoming stream, e.g. .each(new Fields("x"), new IdentityFunction(), new Fields("x")) without renaming.
Common situations: Copy-pasted function wiring reusing the same field name; functions that output the same name as their input; stream merges bringing duplicate field names into one topology node.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Fields order must be same length as pointers map
- duplicate field
- Output fields for chained aggregators must be distinct
- Combiner aggs only take a single field as input. Got this…
- Unknown field name:
AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12).
Data as JSON: /api/errors/0573e7b891157fe1.
Report an issue: GitHub.
Appendix: source
Thrown at storm-core/src/jvm/storm/trident/tuple/TridentTupleView.java:127
public static class OperationOutputFactory implements Factory {
Map<String, ValuePointer> _fieldIndex;
ValuePointer[] _index;
Factory _parent;
public OperationOutputFactory(Factory parent, Fields selfFields) {
_parent = parent;
_fieldIndex = new HashMap(parent.getFieldIndex());
int myIndex = parent.numDelegates();
for(int i=0; i<selfFields.size(); i++) {
String field = selfFields.get(i);
_fieldIndex.put(field, new ValuePointer(myIndex, i, field));
}
List<String> myOrder = new ArrayList<String>(parent.getOutputFields());
Set<String> parentFieldsSet = new HashSet<String>(myOrder);
for(String f: selfFields) {
if(parentFieldsSet.contains(f)) {
throw new IllegalArgumentException(
"Additive operations cannot add fields with same name as already exists. "
+ "Tried adding " + selfFields + " to " + parent.getOutputFields());
}
myOrder.add(f);
}
_index = ValuePointer.buildIndex(new Fields(myOrder), _fieldIndex);
}
public TridentTuple create(TridentTupleView parent, List<Object> selfVals) {
IPersistentVector curr = parent._delegates;
curr = (IPersistentVector) RT.conj(curr, selfVals);
return new TridentTupleView(curr, _index, _fieldIndex);
}
@Override
public Map<String, ValuePointer> getFieldIndex() {
return _fieldIndex;View on GitHub (pinned to cdb116e942)