nathanmarz/storm · error · IllegalArgumentException
Fields for already set
Error message
Fields for ${streamId} already set What it means
OutputFieldsGetter tracks declared streams in _fields; declareStream throws IllegalArgumentException if the same streamId is declared twice. Storm requires each stream id on a component to be declared exactly once. This is a topology-definition (user code) error thrown at topology declaration time.
Solutions
- Declare each stream id only once per component; remove the duplicate declareStream call
- If the default stream is declared via declare(), do not also call declareStream("default", ...)
- Use unique stream ids (e.g. prefix with component-specific names)
- Check for a shared/reused OutputFieldsDeclarer instance and create a fresh one per component
Example fix
// before
declarer.declareStream("default", new Fields("a"));
declarer.declareStream("default", new Fields("b")); // throws
// after
declarer.declareStream("default", new Fields("a"));
declarer.declareStream("secondary", new Fields("b")); Defensive patterns
Strategy: validation
Validate before calling
Set<String> declared = new HashSet<>();
void safeDeclare(OutputFieldsDeclarer d, String streamId, Fields f) {
if (!declared.add(streamId))
throw new IllegalStateException("duplicate stream: " + streamId);
d.declareStream(streamId, f);
} Try / catch
try {
declarer.declareStream(streamId, fields);
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("already set")) throw e;
// log and skip duplicate declaration
} Prevention
- Declare the default stream only via declare(), not declareStream("default", ...)
- Never reuse an OutputFieldsDeclarer across components
- Keep stream-id constants in one place to avoid accidental collisions
When it happens
Trigger: Calling declareStream twice with the same streamId; calling declare() on a component that also already used declareStream("default", ...) for the default stream; an OutputFieldsDeclarer shared/reused across two components (e.g. a cached getter) so ids collide.
Common situations: Dynamic/stream-id built from variables that accidentally repeats; a base class declares the default stream and the subclass declares it again; reusing one OutputFieldsGetter object for multiple components in a builder helper.
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
- A single worker should have 1 SystemBolt instance.
- No output fields defined for component:stream
- Bolt has already been declared for id
- Spout has already been declared for id
- State spout has already been declared for id
AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12).
Data as JSON: /api/errors/4c33b48ec00501c5.
Report an issue: GitHub.
Appendix: source
Thrown at storm-core/src/jvm/backtype/storm/topology/OutputFieldsGetter.java:43
public class OutputFieldsGetter implements OutputFieldsDeclarer {
private Map<String, StreamInfo> _fields = new HashMap<String, StreamInfo>();
public void declare(Fields fields) {
declare(false, fields);
}
public void declare(boolean direct, Fields fields) {
declareStream(Utils.DEFAULT_STREAM_ID, direct, fields);
}
public void declareStream(String streamId, Fields fields) {
declareStream(streamId, false, fields);
}
public void declareStream(String streamId, boolean direct, Fields fields) {
if(_fields.containsKey(streamId)) {
throw new IllegalArgumentException("Fields for " + streamId + " already set");
}
_fields.put(streamId, new StreamInfo(fields.toList(), direct));
}
public Map<String, StreamInfo> getFieldsDeclaration() {
return _fields;
}
}View on GitHub (pinned to cdb116e942)