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

  1. Verify the directory with is_dir($cwd) before constructing/starting the Process.
  2. Create the directory beforehand (mkdir($cwd, 0777, true)) if it should exist.
  3. Log/inspect the resolved cwd value — it may come from config with a wrong default.
  4. 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

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


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)