jenkinsci/jenkins · error · IOException

Can not call launch on a dummy launcher.

Error message

Can not call launch on a dummy launcher.

What it means

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).

Source

Thrown at core/src/main/java/hudson/Launcher.java:1073

                    } catch (InterruptedException e) {
                        // process the interrupt later
                        Thread.currentThread().interrupt();
                    }
                }
            };
        }
    }

    @Restricted(NoExternalUse.class)
    public static class DummyLauncher extends Launcher {

        public DummyLauncher(@NonNull TaskListener listener) {
            super(listener, null);
        }

        @Override
        public Proc launch(ProcStarter starter) throws IOException {
            throw new IOException("Can not call launch on a dummy launcher.");
        }

        @Override
        public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String, String> envVars) throws IOException, InterruptedException {
            throw new IOException("Can not call launchChannel on a dummy launcher.");
        }

        @Override
        public void kill(Map<String, String> modelEnvVars) throws IOException, InterruptedException {
            // Kill method should do nothing.
        }
    }


    /**
     * Launches processes remotely by using the given channel.
     */
    public static class RemoteLauncher extends Launcher {

View on GitHub (pinned to 2e228ff40b)

Solutions

  1. Ensure the code path runs on or targets a real agent (LauncherDecorator or Computer.getLauncher()).
  2. In tests, provide a real or mock Launcher that supports launch instead of DummyLauncher.
  3. Check if the Launcher is an instance of DummyLauncher before calling launch and handle gracefully.

Example fix

// before
launcher.launch().cmds("echo", "hello").start();

// after — guard against dummy
if (launcher instanceof Launcher.DummyLauncher) {
    listener.error("No agent available to launch processes.");
    return;
}
launcher.launch().cmds("echo", "hello").start();
Defensive patterns

Strategy: type-guard

Validate before calling

if (launcher instanceof Launcher.DummyLauncher) {
    throw new IllegalStateException("Cannot launch process: no real agent (DummyLauncher).");
}

Type guard

public static boolean isRealLauncher(Launcher l) {
    return !(l instanceof Launcher.DummyLauncher);
}

Try / catch

try {
    launcher.launch(starter);
} catch (IOException e) {
    if (e.getMessage().contains("dummy launcher")) {
        throw new IllegalStateException("No agent available for process launch", e);
    }
    throw e;
}

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14). Data as JSON: /api/errors/a220bb2d9d1c0d0a. Report an issue: GitHub.