symfony/process · error · RuntimeException

Unable to write temporary ini file.

Error message

Unable to write temporary ini file.

What it means

After assembling the temporary INI content, PhpSubprocess writes it with file_put_contents to a temp file; if the write fails (returns false) the child PHP process cannot be launched with the merged config, so a RuntimeException is thrown immediately.

Solutions

  1. Verify sys_get_temp_dir() exists and is writable: php -r 'var_dump(is_writable(sys_get_temp_dir()));'.
  2. Fix permissions on the temp directory or point sys_temp_dir/tmp to a writable path in php.ini.
  3. Remove open_basedir restrictions or include the temp dir in open_basedir.
  4. Free disk space / raise quota if the filesystem is full.

Example fix

// before
$process = new PhpSubprocess($phpBinary);

// after (fail fast with a clear cause)
$tmp = sys_get_temp_dir();
if (!is_dir($tmp) || !is_writable($tmp)) {
    throw new \RuntimeException(sprintf('Temp dir %s is not writable; PhpSubprocess cannot create its ini file', $tmp));
}
$process = new PhpSubprocess($phpBinary);
Defensive patterns

Strategy: validation

Validate before calling

$tmp = sys_get_temp_dir();
if (!is_dir($tmp) || !is_writable($tmp) || (function_exists('disk_free_space') && disk_free_space($tmp) < 1024 * 1024)) {
    throw new \RuntimeException(sprintf('Temp dir %s unusable for PhpSubprocess ini file', $tmp));
}

Try / catch

try {
    $proc = new PhpSubprocess($phpBinary);
} catch (\RuntimeException $e) {
    if (str_starts_with($e->getMessage(), 'Unable to write temporary ini file')) {
        // check disk space / open_basedir / permissions before retrying
    }
    throw $e;
}

Prevention

When it happens

Trigger: writeTmpIni throws when @file_put_contents($tmpfile, $content) returns false — typically because the temp directory is not writable, the disk is full, an open_basedir restriction excludes the temp path, or the file could not be created.

Common situations: Containers or CI runners with read-only /tmp; open_basedir settings that exclude sys_get_temp_dir(); disk-quota exhaustion; SELinux/AppArmor blocking writes to the temp directory.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

Thrown at PhpSubprocess.php:135

            $content .= $data."\n";
        }

        // Merge loaded settings into our ini content, if it is valid
        $config = parse_ini_string($content);
        $loaded = ini_get_all(null, false);

        if (false === $config || false === $loaded) {
            throw new RuntimeException('Unable to parse ini data.');
        }

        $content .= $this->mergeLoadedConfig($loaded, $config);

        // Work-around for https://bugs.php.net/bug.php?id=75932
        $content .= "opcache.enable_cli=0\n";

        if (false === @file_put_contents($tmpfile, $content)) {
            throw new RuntimeException('Unable to write temporary ini file.');
        }

        return $tmpfile;
    }

    private function mergeLoadedConfig(array $loadedConfig, array $iniConfig): string
    {
        $content = '';

        foreach ($loadedConfig as $name => $value) {
            if (!\is_string($value)) {
                continue;
            }

            if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
                // Double-quote escape each value
                $content .= $name.'="'.addcslashes($value, '\\"')."\"\n";
            }

View on GitHub (pinned to 99b85026db)