sebastianbergmann/phpunit · error · PHPUnit\Util\Xml\XmlException

Could not read XML from file "%s"

Error message

Could not read XML from file "%s"

What it means

Xml\Loader::loadFile() reads a file with error-suppressed file_get_contents() before parsing; when the read fails it throws XmlException('Could not read XML from file "<path>"'). PHPUnit uses this loader for phpunit.xml itself, --configuration targets, baseline files, and migration — so the error usually means the configuration file named on the command line cannot be read.

Source

Thrown at src/Util/Xml/Loader.php:42

/**
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
 *
 * @internal This class is not covered by the backward compatibility promise for PHPUnit
 */
final readonly class Loader
{
    /**
     * @throws XmlException
     */
    public function loadFile(string $filename, bool $ignoreComments = false): DOMDocument
    {
        $reporting = error_reporting(0);
        $contents  = file_get_contents($filename);

        error_reporting($reporting);

        if ($contents === false) {
            throw new XmlException(
                sprintf(
                    'Could not read XML from file "%s"',
                    $filename,
                ),
            );
        }

        if (trim($contents) === '') {
            throw new XmlException(
                sprintf(
                    'Could not parse XML from empty file "%s"',
                    $filename,
                ),
            );
        }

        return $this->load($contents, $ignoreComments);
    }

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Check the path resolves from the directory you invoke PHPUnit in: `test -r path/to/phpunit.xml`
  2. Use an absolute path for --configuration, or cd into the project root so auto-discovery finds phpunit.xml
  3. Fix file permissions if the runner user cannot read it (chown/chmod)
  4. Remove open_basedir restrictions for the config location or move the file inside the allowed paths

Example fix

# before
$ cd /tmp && vendor/bin/phpunit --configuration phpunit.xml
# XmlException: Could not read XML from file "phpunit.xml"

# after
$ vendor/bin/phpunit --configuration /srv/app/phpunit.xml
Defensive patterns

Strategy: validation

Validate before calling

$config = 'phpunit.xml';
if (!is_file($config) || !is_readable($config)) {
    throw new RuntimeException("Configuration {$config} missing or unreadable");
}

Try / catch

use PHPUnit\Util\Xml\XmlException;

try {
    $document = (new Loader)->loadFile($filename);
} catch (XmlException $e) {
    if (str_starts_with($e->getMessage(), 'Could not read XML')) {
        // path problem: fix or fall back to defaults
    }
    throw $e;
}

Prevention

When it happens

Trigger: Running `vendor/bin/phpunit --configuration path/to/phpunit.xml` (or when PHPUnit auto-loads a config) where the file does not exist at that path, is not readable by the current user, or is outside the open_basedir allow-list. Also triggered programmatically via Loader::loadFile() on any missing file.

Common situations: Wrong relative path because PHPUnit was started from a different working directory; config paths broken in CI after directory restructure; permission changes when the CI user changed; open_basedir restrictions on shared hosting.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/67fd23394f68f448. Report an issue: GitHub.