symfony/process · error · RuntimeException
The provided cwd " " does not exist.
Error message
The provided cwd "%s" does not exist.
What it means
Before launching the process, start() validates that the configured working directory exists (is_dir). If the cwd passed to the constructor or setWorkingDirectory does not exist on disk, the process could not start correctly, so a RuntimeException naming the bad path is thrown.
Solutions
- Verify the directory with is_dir($cwd) before constructing/starting the Process.
- Create the directory beforehand (mkdir($cwd, 0777, true)) if it should exist.
- Log/inspect the resolved cwd value — it may come from config with a wrong default.
- Correct the configuration or deployment so the directory exists at runtime.
Example fix
// before
$process = new Process(['composer', 'install'], $projectDir);
$process->run();
// after
if (!is_dir($projectDir)) {
mkdir($projectDir, 0777, true);
}
$process = new Process(['composer', 'install'], $projectDir);
$process->run(); Defensive patterns
Strategy: validation
Validate before calling
$cwd = $options['cwd'] ?? getcwd();
if (!is_dir($cwd)) {
throw new \InvalidArgumentException(sprintf('Working directory does not exist: %s', $cwd));
}
$process = new Process($cmd, $cwd); Try / catch
try {
$process->run();
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'does not exist')) {
mkdir($this->cwd ?? $process->getWorkingDirectory(), 0777, true);
$process->run();
} else {
throw $e;
}
} Prevention
- Validate any config-provided cwd with is_dir at boot time, not at process launch.
- Create working directories during deployment/setup rather than assuming they exist.
- Log the resolved cwd (env-specific config can silently point elsewhere).
- Use realpath() to canonicalize and detect bad paths early.
When it happens
Trigger: new Process($cmd, $cwd) or ->setWorkingDirectory($cwd) with a non-existent path, then calling start()/run(); the check fires just before proc_open on non-Windows-independent code paths after Windows env validation.
Common situations: Hardcoded paths that differ between environments; cwd built from an artifact that was not created yet; typos or trailing configuration mistakes; containers where the directory was never mounted.
Related errors
- A temporary file could not be opened to write the process…
- Unable to write temporary ini file.
- " " yielded a value of type " ", but only scalars and…
- Process is already running.
- Pass the callback to the "Process::start" method or call…
AI-assisted analysis of symfony/process@99b85026db (2026-09-14).
Data as JSON: /api/errors/3413e83dae8c1b88.
Report an issue: GitHub.
Appendix: source
Thrown at Process.php:373
}
$envPairs = [];
foreach ($env as $k => $v) {
if (!\is_scalar($v ?? '') && !$v instanceof \Stringable) {
continue;
}
if (false !== $v && !\in_array($k = (string) $k, ['', 'argc', 'argv', 'ARGC', 'ARGV'], true) && !str_contains($k, '=') && !str_contains($k, "\0")) {
$envPairs[] = $k.'='.$v;
}
}
if ('\\' === \DIRECTORY_SEPARATOR) {
$this->validateWindowsEnvBlockSize($envPairs);
}
if (!is_dir($this->cwd)) {
throw new RuntimeException(\sprintf('The provided cwd "%s" does not exist.', $this->cwd));
}
$lastError = null;
set_error_handler(static function ($type, $msg) use (&$lastError) {
$lastError = $msg;
return true;
});
$oldMask = [];
if ($this->ignoredSignals && \function_exists('pcntl_sigprocmask')) {
// we block signals we want to ignore, as proc_open will use fork / posix_spawn which will copy the signal mask this allow to block
// signals in the child process
pcntl_sigprocmask(\SIG_BLOCK, $this->ignoredSignals, $oldMask);
}
try {View on GitHub (pinned to 99b85026db)