{"record":{"id":"e40024591fb955bc","repo":"nathanmarz/storm","slug":"topology-submission-exception","errorCode":null,"errorMessage":"Topology submission exception","messagePattern":"Topology submission exception","errorType":"console","errorClass":"InvalidTopologyException","httpStatus":null,"severity":"error","filePath":"storm-core/src/jvm/backtype/storm/StormSubmitter.java","lineNumber":101,"sourceCode":"            if(localNimbus!=null) {\n                LOG.info(\"Submitting topology \" + name + \" in local mode\");\n                localNimbus.submitTopology(name, null, serConf, topology);\n            } else {\n                NimbusClient client = NimbusClient.getConfiguredClient(conf);\n                if(topologyNameExists(conf, name)) {\n                    throw new RuntimeException(\"Topology with name `\" + name + \"` already exists on cluster\");\n                }\n                submitJar(conf);\n                try {\n                    LOG.info(\"Submitting topology \" +  name + \" in distributed mode with conf \" + serConf);\n                    if(opts!=null) {\n                        client.getClient().submitTopologyWithOpts(name, submittedJar, serConf, topology, opts);                    \n                    } else {\n                        // this is for backwards compatibility\n                        client.getClient().submitTopology(name, submittedJar, serConf, topology);                                            \n                    }\n                } catch(InvalidTopologyException e) {\n                    LOG.warn(\"Topology submission exception\", e);\n                    throw e;\n                } catch(AlreadyAliveException e) {\n                    LOG.warn(\"Topology already alive exception\", e);\n                    throw e;\n                } finally {\n                    client.close();\n                }\n            }\n            LOG.info(\"Finished submitting topology: \" +  name);\n        } catch(TException e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    private static boolean topologyNameExists(Map conf, String name) {\n        NimbusClient client = NimbusClient.getConfiguredClient(conf);\n        try {\n            ClusterSummary summary = client.getClient().getClusterInfo();","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-core/src/jvm/backtype/storm/StormSubmitter.java#L83-L119","documentation":"StormSubmitter.submitTopology() catches InvalidTopologyException thrown by Nimbus when the submitted topology fails server-side validation (e.g. miswired streams, unbolted spouts, missing declared fields). It logs the exception with the message 'Topology submission exception' and rethrows it, so the caller's submission fails. It is a deliberate server-side rejection of the topology definition, not a transient fault.","triggerScenarios":"Calling StormSubmitter.submitTopology(...) with a topology that Nimbus's validation rejects: a spout/bolt declares input/output streams incorrectly, a component is not wired (setSpout/setBolt mismatches), or grouping references a non-existent stream/component.","commonSituations":"Topology built programmatically with wrong stream/field names; refactor renamed a component but groupings reference the old one; empty or malformed component declarations; serialization problems in declared fields; version drift where a previously accepted topology shape is rejected.","solutions":["Read the nested InvalidTopologyException message — it names the specific component/stream that failed validation.","Check every setBolt(...).shuffleGrouping/fieldsGrouping(...) references an existing component and stream id.","Verify declared output fields of each spout/bolt match what downstream bolts consume (declareOutputFields).","Validate the topology in LocalCluster mode before submitting to the cluster.","Fix the invalid wiring and resubmit; the fix is always in the topology definition, not cluster config."],"exampleFix":"// before\nbuilder.setBolt(\"count\", new CountBolt())\n    .fieldsGrouping(\"splitter\", \"word-stream\", new Fields(\"word\")); // splitter never declared this stream\n// after\nbuilder.setBolt(\"split\", new SplitSentenceBolt());\nbuilder.setBolt(\"count\", new CountBolt())\n    .fieldsGrouping(\"split\", new Fields(\"word\"));","handlingStrategy":"validation","validationCode":"// validate wiring before submitTopology\nfor (String bolt : builder.getBoltIds()) {\n    for (String upstream : builder.getBolt(bolt).getGroupings().keySet()) {\n        if (!builder.getBoltIds().contains(upstream) && !builder.getSpoutIds().contains(upstream))\n            throw new IllegalStateException(bolt + \" consumes from unknown component: \" + upstream);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    StormSubmitter.submitTopology(name, conf, topology);\n} catch (InvalidTopologyException e) {\n    LOG.error(\"Topology rejected by Nimbus: \" + e.get_msg(), e);\n    throw new IllegalArgumentException(\"Fix topology wiring: \" + e.get_msg(), e);\n}","preventionTips":["Test the topology in LocalCluster before every cluster submission.","Keep component ids and stream ids as named constants to avoid typos.","Verify declareOutputFields matches every consuming grouping's Fields.","Run topology wiring checks in CI (build topology and submit to local mode)."],"tags":["topology","validation","submission","nimbus"],"backgroundTag":"schema-validation-failed","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"}