{"record":{"id":"1aebd824418fa978","repo":"nathanmarz/storm","slug":"must-manage-at-least-one-spout","errorCode":null,"errorMessage":"Must manage at least one spout","messagePattern":"Must manage at least one spout","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"storm-core/src/jvm/storm/trident/topology/MasterBatchCoordinator.java","lineNumber":73,"sourceCode":"    TreeMap<Long, TransactionStatus> _activeTx = new TreeMap<Long, TransactionStatus>();\n    TreeMap<Long, Integer> _attemptIds;\n    \n    private SpoutOutputCollector _collector;\n    Long _currTransaction;\n    int _maxTransactionActive;\n    \n    List<ITridentSpout.BatchCoordinator> _coordinators = new ArrayList();\n    \n    \n    List<String> _managedSpoutIds;\n    List<ITridentSpout> _spouts;\n    WindowedTimeThrottler _throttler;\n    \n    boolean _active = true;\n    \n    public MasterBatchCoordinator(List<String> spoutIds, List<ITridentSpout> spouts) {\n        if(spoutIds.isEmpty()) {\n            throw new IllegalArgumentException(\"Must manage at least one spout\");\n        }\n        _managedSpoutIds = spoutIds;\n        _spouts = spouts;\n    }\n\n    @Override\n    public void activate() {\n        _active = true;\n    }\n\n    @Override\n    public void deactivate() {\n        _active = false;\n    }\n        \n    @Override\n    public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {\n        _throttler = new WindowedTimeThrottler((Number)conf.get(Config.TOPOLOGY_TRIDENT_BATCH_EMIT_INTERVAL_MILLIS), 1);","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-core/src/jvm/storm/trident/topology/MasterBatchCoordinator.java#L55-L91","documentation":"MasterBatchCoordinator coordinates transactional batches for the spouts of a Trident topology; constructing it with an empty spoutIds list leaves nothing to manage, so the constructor throws IllegalArgumentException immediately.","triggerScenarios":"Building a Trident topology where the spout registers no managed spout ids — e.g. an empty spout list passed into the coordinator, typically from a mis-built topology or empty spout configuration.","commonSituations":"Programmatic topology construction that conditionally adds spouts and adds none; configuration filter that excludes all spouts; framework code regressing spout registration.","solutions":["Ensure at least one ITridentSpout is registered with the TridentTopology before building","Check the code path that builds spoutIds so it always contains the zk-managed spout entries","If spouts are conditionally configured, validate non-empty spout list before submit"],"exampleFix":"// before\nList<ITridentSpout> spouts = Collections.emptyList();\nnew MasterBatchCoordinator(spoutIds, spouts);\n// after\nif (spouts.isEmpty()) { throw new IllegalStateException(\"Topology must define at least one spout\"); }\nnew MasterBatchCoordinator(spoutIds, spouts);","handlingStrategy":"validation","validationCode":"if (spoutIds == null || spoutIds.isEmpty()) {\n  throw new IllegalArgumentException(\"Topology must define at least one spout\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  MasterBatchCoordinator mbc = new MasterBatchCoordinator(spoutIds, spouts);\n} catch (IllegalArgumentException e) {\n  LOG.error(\"Topology submitted with no spouts configured\", e);\n}","preventionTips":["Validate topology definition (at least one spout) before submit","Check conditional spout-adding code paths for all-empty outcomes","Unit-test topology builders to assert spout registration"],"tags":["storm","trident","topology","validation"],"backgroundTag":"missing-required-argument","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"}