symfony/process · error · RuntimeException

Unable to parse ini data.

Error message

Unable to parse ini data.

What it means

PhpSubprocess builds a temporary INI file that clones the parent PHP process's configuration so the child process runs with identical settings. It validates the assembled content by round-tripping it through parse_ini_string and also checks that ini_get_all succeeded; if either returns false the merged config would be corrupt or incomplete, so it throws RuntimeException instead of launching a broken child.

Solutions

  1. Check that ini_get_all is not in disable_functions and works in your SAPI (php -r 'var_dump(ini_get_all(null,false));').
  2. Inspect the generated ini content for characters that break parse_ini_string (unbalanced quotes, newlines inside values) and fix the source of those values.
  3. Print/load each ini setting with ini_get and sanitize problematic values before constructing PhpSubprocess.
  4. Upgrade/downgrade PHP to a version where ini parsing handles your configuration.

Example fix

// before (debugging the failure)
$subprocess = new PhpSubprocess($phpBinary);

// after (pre-check the ini cache works)
if (false === @ini_get_all(null, false)) {
    throw new \RuntimeException('ini_get_all unavailable; PhpSubprocess cannot snapshot config');
}
$subprocess = new PhpSubprocess($phpBinary);
Defensive patterns

Strategy: validation

Validate before calling

if (!function_exists('ini_get_all') || false === @ini_get_all(null, false)) {
    throw new \RuntimeException('ini_get_all unavailable; PhpSubprocess cannot snapshot PHP config');
}

Try / catch

try {
    $proc = new PhpSubprocess($phpBinary);
} catch (\RuntimeException $e) {
    if ($e->getMessage() === 'Unable to parse ini data.') {
        // fall back to plain PHP binary or log config snapshot failure
    }
    throw $e;
}

Prevention

When it happens

Trigger: writeTmpIni is called from the PhpSubprocess constructor and throws when parse_ini_string($content) returns false (the generated ini text is malformed) or when ini_get_all(null, false) returns false (the ini directive cache is unavailable, e.g. ini directives blocked or an exotic SAPI).

Common situations: Running under a restricted/embedded PHP build where ini_get_all is disabled or fails; exotic PHP versions/patches whose ini parsing rejects the generated content; configs containing values that do not survive the parse round-trip (unbalanced quotes, control characters in ini values inherited from the environment).

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at PhpSubprocess.php:126

        foreach ($iniFiles as $file) {
            // Check for inaccessible ini files
            if (($data = @file_get_contents($file)) === false) {
                throw new RuntimeException('Unable to read ini: '.$file);
            }
            // Check and remove directives after HOST and PATH sections
            if (preg_match('/^\s*\[(?:PATH|HOST)\s*=/mi', $data, $matches, \PREG_OFFSET_CAPTURE)) {
                $data = substr($data, 0, $matches[0][1]);
            }

            $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 = '';

View on GitHub (pinned to 99b85026db)