symfony/process · error · RuntimeException

A temporary file could not be opened to write the process…

Error message

A temporary file could not be opened to write the process output: 

What it means

On Windows, WindowsPipes manages process output through temporary files guarded by .lock files opened with fopen and locked with flock. If fopen on the lock file fails (and the lock file does not already exist, which would mean contention), the constructor throws RuntimeException including the last PHP error message, because output cannot be captured at all.

Solutions

  1. Check the $lastError suffix in the message to identify the underlying fopen failure (permissions, disk full, etc.).
  2. Verify the temp directory (sys_get_temp_dir() / %TEMP%) is writable by the PHP process user.
  3. Free disk space or change TMP/TEMP environment variables to a writable location.
  4. Exclude the temp directory from antivirus/EDR interference and retry.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

if ('\\' === \DIRECTORY_SEPARATOR) {
    $tmp = sys_get_temp_dir();
    if (!is_dir($tmp) || !is_writable($tmp)) {
        throw new \RuntimeException(sprintf('Windows temp dir %s not writable; WindowsPipes will fail', $tmp));
    }
}

Try / catch

try {
    $process = new Process($cmd);
    $process->start();
} catch (\RuntimeException $e) {
    if (str_contains($e->getMessage(), 'A temporary file could not be opened')) {
        // inspect TMP/TEMP permissions and disk space; $lastError is appended to the message
    }
    throw $e;
}

Prevention

When it happens

Trigger: fopen($file.'.lock', 'w') returns false while creating per-pipe temp files in the constructor — disk full, temp directory not writable, or the filesystem denying file creation; $lastError holds the underlying PHP warning text.

Common situations: Windows machines with restricted %TEMP% directories; antivirus or permissions software blocking file creation in the temp path; full disks on CI Windows runners.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of symfony/process@99b85026db (2026-09-14). Data as JSON: /api/errors/c020ea06d1bc3b98. Report an issue: GitHub.

Appendix: source

Thrown at Pipes/WindowsPipes.php:62

            //
            // @see https://bugs.php.net/51800
            $pipes = [
                Process::STDOUT => Process::OUT,
                Process::STDERR => Process::ERR,
            ];
            $tmpDir = sys_get_temp_dir();
            $lastError = 'unknown reason';
            set_error_handler(static function ($type, $msg) use (&$lastError) { $lastError = $msg; });
            for ($i = 0;; ++$i) {
                foreach ($pipes as $pipe => $name) {
                    $file = \sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);

                    if (!$h = fopen($file.'.lock', 'w')) {
                        if (file_exists($file.'.lock')) {
                            continue 2;
                        }
                        restore_error_handler();
                        throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError);
                    }
                    if (!flock($h, \LOCK_EX | \LOCK_NB)) {
                        continue 2;
                    }
                    if (isset($this->lockHandles[$pipe])) {
                        flock($this->lockHandles[$pipe], \LOCK_UN);
                        fclose($this->lockHandles[$pipe]);
                    }
                    $this->lockHandles[$pipe] = $h;

                    if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) {
                        flock($this->lockHandles[$pipe], \LOCK_UN);
                        fclose($this->lockHandles[$pipe]);
                        unset($this->lockHandles[$pipe]);
                        continue 2;
                    }
                    $this->fileHandles[$pipe] = $h;
                    $this->files[$pipe] = $file;

View on GitHub (pinned to 99b85026db)