nathanmarz/storm · error · RuntimeException

Trident does not support direct emits from spouts

Error message

Trident does not support direct emits from spouts

What it means

RichSpoutBatchTriggerer wraps an IBatchSpout or rich spout for Trident and overrides emitDirect to throw a RuntimeException, because Trident does not support direct emissions from spouts. A spout attempting a direct emit inside a Trident batch will hit this immediately at runtime.

Solutions

  1. Rewrite the spout to use collector.emit only; remove all emitDirect paths.
  2. If direct emission is essential, run the spout in a plain Storm topology rather than Trident.
  3. Substitute Trident-supported groupings (shuffle, fields, partialKey) for direct targeting.
  4. Add an integration test running the spout under Trident to catch direct-emit paths before deployment.

Example fix

// before
collector.emitDirect(taskId, stream, tuple, msgId);
// after
collector.emit(stream, tuple, msgId);
Defensive patterns

Strategy: validation

Validate before calling

// Java: before deploying, verify batch spout implementation has no emitDirect path
// static audit: ensure no call sites of _collector.emitDirect( in spout classes

Prevention

When it happens

Trigger: A batch spout or wrapped spout implementation calls its collector's emitDirect(task, stream, values, msgId) while running under Trident; the wrapper's collector rejects the call.

Common situations: Porting raw Storm spouts using direct grouping into Trident; spout frameworks that emit conditionally direct vs regular; library spouts with emitDirect paths not documented as Trident-incompatible.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at storm-core/src/jvm/storm/trident/spout/RichSpoutBatchTriggerer.java:168

            finish.msgId = msgId;
            List<Integer> tasks = _collector.emit(_stream, new ConsList(batchId, values));
            Set<Integer> outTasksSet = new HashSet<Integer>(tasks);
            for(Integer t: _outputTasks) {
                int count = 0;
                if(outTasksSet.contains(t)) {
                    count = 1;
                }
                long r = _rand.nextLong();
                _collector.emitDirect(t, _coordStream, new Values(batchId, count), r);
                finish.vals.add(r);
            }
            _finishConditions.put(batchIdVal, finish);
            return tasks;
        }

        @Override
        public void emitDirect(int task, String ignore, List<Object> values, Object msgId) {
            throw new RuntimeException("Trident does not support direct emits from spouts");
        }

        @Override
        public void reportError(Throwable t) {
            _collector.reportError(t);
        }
        
    }
}

View on GitHub (pinned to cdb116e942)