sebastianbergmann/phpunit · warning · PHPUnit\TextUI\XmlConfiguration\Exception
The file does not need to be migrated
Error message
The file does not need to be migrated
What it means
Migrator::migrate() throws this when the file already validates against the schema of the currently installed PHPUnit series AND its xsi:schemaLocation attribute is already current, so no migration step would change anything. It is PHPUnit's way of saying the command is a no-op, surfaced as an exception rather than a success message.
Source
Thrown at src/TextUI/Configuration/Xml/Migration/Migrator.php:44
{
/**
* @throws Exception
* @throws MigrationException
* @throws XmlException
*/
public function migrate(string $filename): string
{
$origin = (new SchemaDetector)->detect($filename);
if (!$origin->detected()) {
throw new Exception('The file does not validate against any known schema');
}
$configurationDocument = (new XmlLoader)->loadFile($filename);
if ($origin->version() === Version::series()) {
if (!$this->schemaLocationNeedsUpdate($configurationDocument)) {
throw new Exception('The file does not need to be migrated');
}
(new UpdateSchemaLocation)->migrate($configurationDocument);
} else {
foreach ((new MigrationBuilder)->build($origin->version()) as $migration) {
$migration->migrate($configurationDocument);
}
}
$configurationDocument->formatOutput = true;
$configurationDocument->preserveWhiteSpace = false;
$xml = $configurationDocument->saveXML();
assert($xml !== false);
return $xml;
}View on GitHub (pinned to f123cdb2a2)
Solutions
- Treat it as confirmation that the configuration is already current — nothing to fix
- Remove or make the CI migration step conditional (only when the config predates the installed series)
- In automation, catch this specific exception and continue with exit code 0
Example fix
# before (CI fails on no-op migration) vendor/bin/phpunit --migrate-configuration # after (script tolerates 'nothing to do') vendor/bin/phpunit --migrate-configuration || echo 'Configuration already current'
Defensive patterns
Strategy: fallback
Validate before calling
// Skip migration when the config already matches the installed series
$result = (new \PHPUnit\TextUI\XmlConfiguration\SchemaDetector)->detect('phpunit.xml');
$alreadyCurrent = $result->detected()
&& $result->version() === \PHPUnit\Runner\Version::series();
if (!$alreadyCurrent) {
system('vendor/bin/phpunit --migrate-configuration');
} else {
echo 'phpunit.xml already current, skipping migration' . PHP_EOL;
} Try / catch
try {
(new \PHPUnit\TextUI\XmlConfiguration\Migration\Migrator)->migrate($file);
} catch (\PHPUnit\TextUI\XmlConfiguration\Exception $e) {
if (str_contains($e->getMessage(), 'does not need to be migrated')) {
// intended state: treat as success and continue the pipeline
return 0;
}
throw $e;
} Prevention
- Treat this message as a no-op signal, not a failure; don't run --migrate-configuration unconditionally in CI
- Gate the migration step on the schema detection result or delete the step after an upgrade project ends
- Remember schemaLocation updates alone also count as a migration; freshly generated configs may still be 'current'
When it happens
Trigger: Running `vendor/bin/phpunit --migrate-configuration` on a configuration that was already migrated in a previous run; CI pipelines that unconditionally run the migration step on every build even after the config was committed in current form.
Common situations: A migration step left in CI after the upgrade project finished; developers re-running the command 'just to be sure' after updating PHPUnit within the same major series.
Related errors
- Cannot load XML configuration file %s
- The file does not validate against any known schema
- Parameter "%s" does not exist
- Invalid version comparison operator: "%s"
- Default test suite is not configured
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/1342254850efb27e.
Report an issue: GitHub.