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

  1. Rename the newly added fields, e.g. new Fields("x_copy"), or use each with a different output name
  2. Use a projection (new Fields(...)) to drop conflicting parent fields before the operation
  3. 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

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


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)