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
- 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.
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
- 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.
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
- Process working directory '%s' doesn't exist!
- Can not call launchChannel on a dummy launcher.
- Failed to join the process
- Failed to unpack %s (%d bytes read)
- remote file operation failed
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/a220bb2d9d1c0d0a.
Report an issue: GitHub.