{"record":{"id":"3be1c671284d9e9c","repo":"nathanmarz/storm","slug":"must-submit-topologies-using-the-storm-client-script-so-that","errorCode":null,"errorMessage":"Must submit topologies using the 'storm' client script so that StormSubmitter knows which jar to upload.","messagePattern":"Must submit topologies using the 'storm' client script so that StormSubmitter knows which jar to upload\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"storm-core/src/jvm/backtype/storm/StormSubmitter.java","lineNumber":148,"sourceCode":"            client.close();\n        }\n    }\n\n    private static String submittedJar = null;\n    \n    private static void submitJar(Map conf) {\n        if(submittedJar==null) {\n            LOG.info(\"Jar not uploaded to master yet. Submitting jar...\");\n            String localJar = System.getProperty(\"storm.jar\");\n            submittedJar = submitJar(conf, localJar);\n        } else {\n            LOG.info(\"Jar already uploaded to master. Not submitting jar.\");\n        }\n    }\n    \n    public static String submitJar(Map conf, String localJar) {\n        if(localJar==null) {\n            throw new RuntimeException(\"Must submit topologies using the 'storm' client script so that StormSubmitter knows which jar to upload.\");\n        }\n        NimbusClient client = NimbusClient.getConfiguredClient(conf);\n        try {\n            String uploadLocation = client.getClient().beginFileUpload();\n            LOG.info(\"Uploading topology jar \" + localJar + \" to assigned location: \" + uploadLocation);\n            BufferFileInputStream is = new BufferFileInputStream(localJar);\n            while(true) {\n                byte[] toSubmit = is.read();\n                if(toSubmit.length==0) break;\n                client.getClient().uploadChunk(uploadLocation, ByteBuffer.wrap(toSubmit));\n            }\n            client.getClient().finishFileUpload(uploadLocation);\n            LOG.info(\"Successfully uploaded topology jar to assigned location: \" + uploadLocation);\n            return uploadLocation;\n        } catch(Exception e) {\n            throw new RuntimeException(e);            \n        } finally {\n            client.close();","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-core/src/jvm/backtype/storm/StormSubmitter.java#L130-L166","documentation":"submitJar requires the localJar path to be non-null; the 'storm' client script sets it so StormSubmitter knows which jar to upload to Nimbus. Running the topology's main class directly (e.g. `java -cp ... Main`) leaves localJar null, so a RuntimeException is thrown.","triggerScenarios":"Running the topology main class with plain `java` instead of the `storm jar` wrapper; calling StormSubmitter.submitTopology from a context where the jar path was never injected; running from an IDE without the storm client script.","commonSituations":"IDE run configurations launching topology main directly; local tests accidentally calling submitTopology; docs examples copied without using the storm CLI.","solutions":["Submit via the storm client: `storm jar mytopology.jar com.mypack.MyTopology <name>`.","If you must launch with java, set the jar path yourself and call StormSubmitter.submitJar(conf, localJar) explicitly.","For IDEs, create a run configuration that mimics the storm script or use local mode (LocalCluster) instead.","Guard the code: only call submitTopology when running under the storm script."],"exampleFix":"// before\nStormSubmitter.submitTopology(name, conf, topology); // run via plain java\n// after - guard\nif (System.getProperty(\"storm.jar\") == null) {\n    throw new IllegalStateException(\"Run with: storm jar app.jar ...\");\n}\nStormSubmitter.submitTopology(name, conf, topology);","handlingStrategy":"validation","validationCode":"// ensure we're running under 'storm jar' before submitting\nif (System.getProperty(\"storm.jar\") == null) {\n    throw new IllegalStateException(\"Use: storm jar <jar> <mainClass> ...\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    StormSubmitter.submitTopology(name, conf, topology);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"'storm' client script\")) {\n        log.error(\"Re-run via: storm jar app.jar \" + Main.class.getName());\n    } else { throw e; }\n}","preventionTips":["Always deploy via the storm CLI wrapper, never plain java for remote submit.","Use LocalCluster for IDE/debug runs instead of submitTopology.","Add the storm.jar system-property check at the top of your main method."],"tags":["deployment","cli","jar-upload","storm"],"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"}