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
- Check the path resolves from the directory you invoke PHPUnit in: `test -r path/to/phpunit.xml`
- Use an absolute path for --configuration, or cd into the project root so auto-discovery finds phpunit.xml
- Fix file permissions if the runner user cannot read it (chown/chmod)
- 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
- Invoke PHPUnit from the project root so auto-discovery finds phpunit.xml without --configuration
- Use absolute paths for --configuration in wrapper scripts and CI
- Add `test -r phpunit.xml` to CI preflight steps
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
- Parameter "%s" does not exist
- Cannot load XML configuration file %s
- Invalid version comparison operator: "%s"
- The file does not validate against any known schema
- The file does not need to be migrated
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/67fd23394f68f448.
Report an issue: GitHub.