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
- Check the $lastError suffix in the message to identify the underlying fopen failure (permissions, disk full, etc.).
- Verify the temp directory (sys_get_temp_dir() / %TEMP%) is writable by the PHP process user.
- Free disk space or change TMP/TEMP environment variables to a writable location.
- 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
- On Windows hosts, ensure %TEMP% is writable by the PHP service account.
- Exclude the temp directory from antivirus/EDR that blocks transient file creation.
- Monitor disk space on Windows CI runners.
- Set TMP/TEMP env vars to a known-writable directory in constrained environments.
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
- Unable to write temporary ini file.
- The provided cwd " " does not exist.
- " " 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/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)