nathanmarz/storm · error · InvalidTopologyException

Topology submission exception

Error message

Topology submission exception

What it means

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.

Solutions

  1. Read the nested InvalidTopologyException message — it names the specific component/stream that failed validation.
  2. Check every setBolt(...).shuffleGrouping/fieldsGrouping(...) references an existing component and stream id.
  3. Verify declared output fields of each spout/bolt match what downstream bolts consume (declareOutputFields).
  4. Validate the topology in LocalCluster mode before submitting to the cluster.
  5. Fix the invalid wiring and resubmit; the fix is always in the topology definition, not cluster config.

Example fix

// before
builder.setBolt("count", new CountBolt())
    .fieldsGrouping("splitter", "word-stream", new Fields("word")); // splitter never declared this stream
// after
builder.setBolt("split", new SplitSentenceBolt());
builder.setBolt("count", new CountBolt())
    .fieldsGrouping("split", new Fields("word"));
Defensive patterns

Strategy: validation

Validate before calling

// validate wiring before submitTopology
for (String bolt : builder.getBoltIds()) {
    for (String upstream : builder.getBolt(bolt).getGroupings().keySet()) {
        if (!builder.getBoltIds().contains(upstream) && !builder.getSpoutIds().contains(upstream))
            throw new IllegalStateException(bolt + " consumes from unknown component: " + upstream);
    }
}

Try / catch

try {
    StormSubmitter.submitTopology(name, conf, topology);
} catch (InvalidTopologyException e) {
    LOG.error("Topology rejected by Nimbus: " + e.get_msg(), e);
    throw new IllegalArgumentException("Fix topology wiring: " + e.get_msg(), e);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at storm-core/src/jvm/backtype/storm/StormSubmitter.java:101

            if(localNimbus!=null) {
                LOG.info("Submitting topology " + name + " in local mode");
                localNimbus.submitTopology(name, null, serConf, topology);
            } else {
                NimbusClient client = NimbusClient.getConfiguredClient(conf);
                if(topologyNameExists(conf, name)) {
                    throw new RuntimeException("Topology with name `" + name + "` already exists on cluster");
                }
                submitJar(conf);
                try {
                    LOG.info("Submitting topology " +  name + " in distributed mode with conf " + serConf);
                    if(opts!=null) {
                        client.getClient().submitTopologyWithOpts(name, submittedJar, serConf, topology, opts);                    
                    } else {
                        // this is for backwards compatibility
                        client.getClient().submitTopology(name, submittedJar, serConf, topology);                                            
                    }
                } catch(InvalidTopologyException e) {
                    LOG.warn("Topology submission exception", e);
                    throw e;
                } catch(AlreadyAliveException e) {
                    LOG.warn("Topology already alive exception", e);
                    throw e;
                } finally {
                    client.close();
                }
            }
            LOG.info("Finished submitting topology: " +  name);
        } catch(TException e) {
            throw new RuntimeException(e);
        }
    }
    
    private static boolean topologyNameExists(Map conf, String name) {
        NimbusClient client = NimbusClient.getConfiguredClient(conf);
        try {
            ClusterSummary summary = client.getClient().getClusterInfo();

View on GitHub (pinned to cdb116e942)