{"record":{"id":"1342254850efb27e","repo":"sebastianbergmann/phpunit","slug":"the-file-does-not-need-to-be-migrated","errorCode":null,"errorMessage":"The file does not need to be migrated","messagePattern":"The file does not need to be migrated","errorType":"exception","errorClass":"PHPUnit\\TextUI\\XmlConfiguration\\Exception","httpStatus":null,"severity":"warning","filePath":"src/TextUI/Configuration/Xml/Migration/Migrator.php","lineNumber":44,"sourceCode":"{\n    /**\n     * @throws Exception\n     * @throws MigrationException\n     * @throws XmlException\n     */\n    public function migrate(string $filename): string\n    {\n        $origin = (new SchemaDetector)->detect($filename);\n\n        if (!$origin->detected()) {\n            throw new Exception('The file does not validate against any known schema');\n        }\n\n        $configurationDocument = (new XmlLoader)->loadFile($filename);\n\n        if ($origin->version() === Version::series()) {\n            if (!$this->schemaLocationNeedsUpdate($configurationDocument)) {\n                throw new Exception('The file does not need to be migrated');\n            }\n\n            (new UpdateSchemaLocation)->migrate($configurationDocument);\n        } else {\n            foreach ((new MigrationBuilder)->build($origin->version()) as $migration) {\n                $migration->migrate($configurationDocument);\n            }\n        }\n\n        $configurationDocument->formatOutput       = true;\n        $configurationDocument->preserveWhiteSpace = false;\n\n        $xml = $configurationDocument->saveXML();\n\n        assert($xml !== false);\n\n        return $xml;\n    }","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/TextUI/Configuration/Xml/Migration/Migrator.php#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before (CI fails on no-op migration)\nvendor/bin/phpunit --migrate-configuration\n\n# after (script tolerates 'nothing to do')\nvendor/bin/phpunit --migrate-configuration || echo 'Configuration already current'","handlingStrategy":"fallback","validationCode":"// Skip migration when the config already matches the installed series\n$result = (new \\PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetector)->detect('phpunit.xml');\n\n$alreadyCurrent = $result->detected()\n    && $result->version() === \\PHPUnit\\Runner\\Version::series();\n\nif (!$alreadyCurrent) {\n    system('vendor/bin/phpunit --migrate-configuration');\n} else {\n    echo 'phpunit.xml already current, skipping migration' . PHP_EOL;\n}","typeGuard":null,"tryCatchPattern":"try {\n    (new \\PHPUnit\\TextUI\\XmlConfiguration\\Migration\\Migrator)->migrate($file);\n} catch (\\PHPUnit\\TextUI\\XmlConfiguration\\Exception $e) {\n    if (str_contains($e->getMessage(), 'does not need to be migrated')) {\n        // intended state: treat as success and continue the pipeline\n        return 0;\n    }\n    throw $e;\n}","preventionTips":["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'"],"tags":["phpunit","xml","migration","no-op","configuration"],"backgroundTag":"migration-not-needed","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}