{"record":{"id":"a220bb2d9d1c0d0a","repo":"jenkinsci/jenkins","slug":"can-not-call-launch-on-a-dummy-launcher","errorCode":null,"errorMessage":"Can not call launch on a dummy launcher.","messagePattern":"Can not call launch on a dummy launcher\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/hudson/Launcher.java","lineNumber":1073,"sourceCode":"                    } catch (InterruptedException e) {\n                        // process the interrupt later\n                        Thread.currentThread().interrupt();\n                    }\n                }\n            };\n        }\n    }\n\n    @Restricted(NoExternalUse.class)\n    public static class DummyLauncher extends Launcher {\n\n        public DummyLauncher(@NonNull TaskListener listener) {\n            super(listener, null);\n        }\n\n        @Override\n        public Proc launch(ProcStarter starter) throws IOException {\n            throw new IOException(\"Can not call launch on a dummy launcher.\");\n        }\n\n        @Override\n        public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String, String> envVars) throws IOException, InterruptedException {\n            throw new IOException(\"Can not call launchChannel on a dummy launcher.\");\n        }\n\n        @Override\n        public void kill(Map<String, String> modelEnvVars) throws IOException, InterruptedException {\n            // Kill method should do nothing.\n        }\n    }\n\n\n    /**\n     * Launches processes remotely by using the given channel.\n     */\n    public static class RemoteLauncher extends Launcher {","sourceCodeStart":1055,"sourceCodeEnd":1091,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/core/src/main/java/hudson/Launcher.java#L1055-L1091","documentation":"DummyLauncher is a Launcher subclass that cannot actually launch processes — it is constructed with only a TaskListener and no channel/computer. Calling launch(ProcStarter) throws IOException. This is used in contexts where a Launcher object is required by the type system but no real process execution is available (e.g., headless test harnesses, or build steps invoked outside an agent context).","triggerScenarios":"A build step, plugin code, or pipeline step calls Launcher.launch() on a DummyLauncher instance — typically because the FilePath/Launcher was obtained from a context that has no real agent (e.g., running on the controller without a node, or in a unit test using DummyLauncher).","commonSituations":"Unit tests using JenkinsRule that inadvertently trigger a real process launch on a DummyLauncher; plugin code running during Jenkins startup before any agent is connected; or a pipeline that tries to sh/bat on a nodeless context.","solutions":["Ensure the code path runs on or targets a real agent (LauncherDecorator or Computer.getLauncher()).","In tests, provide a real or mock Launcher that supports launch instead of DummyLauncher.","Check if the Launcher is an instance of DummyLauncher before calling launch and handle gracefully."],"exampleFix":"// before\nlauncher.launch().cmds(\"echo\", \"hello\").start();\n\n// after — guard against dummy\nif (launcher instanceof Launcher.DummyLauncher) {\n    listener.error(\"No agent available to launch processes.\");\n    return;\n}\nlauncher.launch().cmds(\"echo\", \"hello\").start();","handlingStrategy":"type-guard","validationCode":"if (launcher instanceof Launcher.DummyLauncher) {\n    throw new IllegalStateException(\"Cannot launch process: no real agent (DummyLauncher).\");\n}","typeGuard":"public static boolean isRealLauncher(Launcher l) {\n    return !(l instanceof Launcher.DummyLauncher);\n}","tryCatchPattern":"try {\n    launcher.launch(starter);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"dummy launcher\")) {\n        throw new IllegalStateException(\"No agent available for process launch\", e);\n    }\n    throw e;\n}","preventionTips":["Always obtain a Launcher from a real Computer/Node context.","In tests, use a mock or real Launcher instead of DummyLauncher for process-launching code paths."],"tags":["launcher","process","dummy","agent"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}