{"record":{"id":"1c0465b6e54ef34c","repo":"nathanmarz/storm","slug":"regular-rich-spouts-not-supported-yet-try-wrapping-in-a","errorCode":null,"errorMessage":"Regular rich spouts not supported yet... try wrapping in a RichSpoutBatchExecutor","messagePattern":"Regular rich spouts not supported yet\\.\\.\\. try wrapping in a RichSpoutBatchExecutor","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"storm-core/src/jvm/storm/trident/TridentTopology.java","lineNumber":398,"sourceCode":"        \n        TridentTopologyBuilder builder = new TridentTopologyBuilder();\n        \n        Map<Node, String> spoutIds = genSpoutIds(spoutNodes);\n        Map<Group, String> boltIds = genBoltIds(mergedGroups);\n        \n        for(SpoutNode sn: spoutNodes) {\n            Integer parallelism = parallelisms.get(grouper.nodeGroup(sn));\n            if(sn.type == SpoutNode.SpoutType.DRPC) {\n                builder.setBatchPerTupleSpout(spoutIds.get(sn), sn.streamId,\n                        (IRichSpout) sn.spout, parallelism, batchGroupMap.get(sn));\n            } else {\n                ITridentSpout s;\n                if(sn.spout instanceof IBatchSpout) {\n                    s = new BatchSpoutExecutor((IBatchSpout)sn.spout);\n                } else if(sn.spout instanceof ITridentSpout) {\n                    s = (ITridentSpout) sn.spout;\n                } else {\n                    throw new RuntimeException(\"Regular rich spouts not supported yet... try wrapping in a RichSpoutBatchExecutor\");\n                    // TODO: handle regular rich spout without batches (need lots of updates to support this throughout)\n                }\n                builder.setSpout(spoutIds.get(sn), sn.streamId, sn.txId, s, parallelism, batchGroupMap.get(sn));\n            }\n        }\n        \n        for(Group g: mergedGroups) {\n            if(!isSpoutGroup(g)) {\n                Integer p = parallelisms.get(g);\n                Map<String, String> streamToGroup = getOutputStreamBatchGroups(g, batchGroupMap);\n                BoltDeclarer d = builder.setBolt(boltIds.get(g), new SubtopologyBolt(graph, g.nodes, batchGroupMap), p,\n                        committerBatches(g, batchGroupMap), streamToGroup);\n                Collection<PartitionNode> inputs = uniquedSubscriptions(externalGroupInputs(g));\n                for(PartitionNode n: inputs) {\n                    Node parent = TridentUtils.getParent(graph, n);\n                    String componentId;\n                    if(parent instanceof SpoutNode) {\n                        componentId = spoutIds.get(parent);","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-core/src/jvm/storm/trident/TridentTopology.java#L380-L416","documentation":"Trident topologies only accept spouts implementing IBatchSpout or ITridentSpout. During TridentTopology.build(), any spout node that is a plain Storm IRichSpout hits this else branch and a RuntimeException is thrown. Trident is batch-oriented and has no path for regular continuous spouts (the TODO comments note full support was never added).","triggerScenarios":"newStream() fed from a spout created via topology.addSpout or TridentTopology.newStream(name, irichSpout) where the spout only implements IRichSpout, then calling build().","commonSituations":"Migrating an existing Storm topology to Trident and reusing the old IRichSpout; third-party connector spouts written for core Storm; tutorials mixing Trident API with classic spout implementations.","solutions":["Wrap the IRichSpout with RichSpoutBatchExecutor: TridentTopology.newStream(name, new RichSpoutBatchExecutor(spout))","Implement ITridentSpout (or IBatchSpout) instead of IRichSpout","Use an existing Trident-native connector for your data source"],"exampleFix":"// before\nTridentTopology topology = new TridentTopology();\ntopology.newStream(\"spout\", new MyRichSpout());\n// after\ntopology.newStream(\"spout\", new RichSpoutBatchExecutor(new MyRichSpout()));","handlingStrategy":"type-guard","validationCode":"if (!(spout instanceof IBatchSpout || spout instanceof ITridentSpout)) {\n    spout = new RichSpoutBatchExecutor((IRichSpout) spout);\n}","typeGuard":"boolean isTridentCompatible(Object spout) {\n    return spout instanceof IBatchSpout || spout instanceof ITridentSpout;\n}","tryCatchPattern":"try {\n    topology.newStream(\"s\", spout);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"Regular rich spouts not supported\")) {\n        throw new IllegalStateException(\"Wrap IRichSpout in RichSpoutBatchExecutor before use\", e);\n    } throw e;\n}","preventionTips":["Never pass raw IRichSpout into TridentTopology.newStream","Standardize a factory method that wraps spouts in RichSpoutBatchExecutor","Prefer Trident-native spout implementations when available"],"tags":["storm","trident","spout","unsupported"],"backgroundTag":"unsupported-operation","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"}