jenkinsci/jenkins · error · IOException
Process working directory '%s' doesn't exist!
Error message
Process working directory '%s' doesn't exist!
What it means
Thrown in the LocalProc constructor when the ProcessBuilder's configured working directory exists as a path object but does not actually exist on the filesystem. The message includes the absolute path of the missing directory. This is a pre-launch guard before procBuilder.start() is called.
Source
Thrown at core/src/main/java/hudson/Proc.java:247
if (env != null) {
Map<String, String> m = pb.environment();
m.clear();
for (String e : env) {
int idx = e.indexOf('=');
m.put(e.substring(0, idx), e.substring(idx + 1));
}
}
return pb;
}
private LocalProc(String name, ProcessBuilder procBuilder, InputStream in, OutputStream out, OutputStream err) throws IOException {
Logger.getLogger(Proc.class.getName()).log(Level.FINE, "Running: {0}", name);
this.name = name;
this.out = out;
this.cookie = EnvVars.createCookie();
procBuilder.environment().putAll(cookie);
if (procBuilder.directory() != null && !procBuilder.directory().exists()) {
throw new IOException(String.format("Process working directory '%s' doesn't exist!", procBuilder.directory().getAbsolutePath()));
}
this.proc = procBuilder.start();
InputStream procInputStream = proc.getInputStream();
if (out == SELFPUMP_OUTPUT) {
stdout = procInputStream;
copier = null;
} else {
copier = new StreamCopyThread(name + ": stdout copier", procInputStream, out);
copier.start();
stdout = null;
}
if (in == null) {
// nothing to feed to stdin
stdin = null;
proc.getOutputStream().close();
} elseView on GitHub (pinned to 2e228ff40b)
Solutions
- Verify the agent's 'Remote root directory' setting in Manage Jenkins → Nodes points to an existing, writable directory.
- Ensure any custom workspace path passed to the launcher is created before launching the process (e.g., via a pre-build shell step that runs mkdir -p).
- Check for external cleanup (cron jobs, disk cleanup plugins) that may have deleted the directory.
- If running inside a container, verify the volume mount for the workspace is correctly configured and the mount point exists.
Example fix
// before
Launcher launcher = node.createLauncher(taskListener);
launcher.launch().cmds(cmds).pwd(workspacePath).start();
// after
if (!Files.exists(workspacePath)) {
Files.createDirectories(workspacePath);
}
Launcher launcher = node.createLauncher(taskListener);
launcher.launch().cmds(cmds).pwd(workspacePath).start(); Defensive patterns
Strategy: validation
Validate before calling
// Validate working directory before launching
Path workDir = node.getRootPath().toPath(); // or custom workspace
if (!Files.exists(workDir)) {
Files.createDirectories(workDir);
}
Launcher launcher = node.createLauncher(listener); Try / catch
try {
proc = launcher.launch().cmds(cmds).pwd(workDir).start();
} catch (IOException e) {
if (e.getMessage().contains("doesn't exist")) {
// Recreate directory and retry once
Files.createDirectories(workDir);
proc = launcher.launch().cmds(cmds).pwd(workDir).start();
} else {
throw e;
}
} Prevention
- Verify agent root directory exists and is writable during agent provisioning.
- Use a pre-build step to ensure workspace directories exist (mkdir -p).
- Monitor agent disk health — stale mounts and full disks can cause path issues.
When it happens
Trigger: A Launcher.LocalLauncher (or direct LocalProc instantiation) creates a ProcessBuilder with directory() set to a path, then checks procBuilder.directory().exists() — if false, it throws. The check runs after cookie/cookie env injection but before procBuilder.start().
Common situations: An agent's remote FS root (configured in node settings) points to a deleted or unmounted directory; a build step references a custom workspace path that was cleaned up by a previous build or never created; running on a Docker container where the mount point for the workspace is not present; a tool installer's home directory was removed.
Related errors
- Can not call launch on a dummy launcher.
- Failed to create a temp file on ${remote}
- Failed to create a temp directory on ${remote}
- Failed to join the process
- Could not get TcpSlaveAgentListener host name
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/1891006dfd97aa4f.
Report an issue: GitHub.