{"record":{"id":"ef1948d680b523d7","repo":"sebastianbergmann/phpunit","slug":"invalid-version-comparison-operator-s","errorCode":null,"errorMessage":"Invalid version comparison operator: \"%s\"","messagePattern":"Invalid version comparison operator: \"(.+?)\"","errorType":"validation","errorClass":"PHPUnit\\TextUI\\XmlConfiguration\\Exception","httpStatus":null,"severity":"error","filePath":"src/TextUI/Configuration/Xml/Loader.php","lineNumber":976,"sourceCode":"        $value = $element->getAttribute($attribute);\n\n        if ($value === '') {\n            return $default;\n        }\n\n        return $value;\n    }\n\n    /**\n     * @throws Exception\n     *\n     * @return '!='|'<'|'<='|'<>'|'='|'=='|'>'|'>='|'eq'|'ge'|'gt'|'le'|'lt'|'ne'\n     */\n    private function parseVersionOperator(string $operator): string\n    {\n        return match ($operator) {\n            '!=', '<', '<=', '<>', '=', '==', '>', '>=', 'eq', 'ge', 'gt', 'le', 'lt', 'ne' => $operator,\n            default                                                                         => throw new Exception(sprintf('Invalid version comparison operator: \"%s\"', $operator)),\n        };\n    }\n\n    private function parseInteger(string $value, int $default): int\n    {\n        if (is_numeric($value)) {\n            return (int) $value;\n        }\n\n        return $default;\n    }\n\n    private function php(string $filename, DOMXPath $xpath): Php\n    {\n        $includePaths = [];\n\n        $includePathNodes = $xpath->query('php/includePath');\n","sourceCodeStart":958,"sourceCodeEnd":994,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/TextUI/Configuration/Xml/Loader.php#L958-L994","documentation":"The phpVersionOperator attribute on <directory> and <file> entries inside <testsuite> (and source restrictions) must be one of PHP's version_compare() operators: !=, <, <=, <>, =, ==, >, >=, eq, ge, gt, le, lt, ne. parseVersionOperator() throws for anything else. This is version_compare syntax, not composer semver syntax, so '^', '~', '=~' and similar are invalid.","triggerScenarios":"`<directory phpVersion=\"8.1\" phpVersionOperator=\"^\">tests</directory>`; phpVersionOperator=\"=~\"; phpVersionOperator=\"===\"; misspellings like \"greate\"; copying a composer.json constraint into the attribute.","commonSituations":"Developers familiar with composer version constraints writing phpunit.xml by hand; copy-pasted snippets from blogs using semver operators; config generators emitting wrong operator strings.","solutions":["Use a version_compare operator: `<`, `<=`, `>`, `>=`, `=`, `==`, `!=`, `<>` or the word forms lt, le, gt, ge, eq, ne","For 'PHP 8.1 or newer' use phpVersion=\"8.1.0\" phpVersionOperator=\">=\"","Remember the comparison uses PHP's version_compare() rules, so write full version strings like 8.1.0"],"exampleFix":"<!-- before -->\n<directory phpVersion=\"8.1\" phpVersionOperator=\"^\">tests/Php81</directory>\n\n<!-- after -->\n<directory phpVersion=\"8.1.0\" phpVersionOperator=\">=\">tests/Php81</directory>","handlingStrategy":"validation","validationCode":"const VALID_OPERATORS = ['!=', '<', '<=', '<>', '=', '==', '>', '>=', 'eq', 'ge', 'gt', 'le', 'lt', 'ne'];\n\nfunction validPhpVersionOperator(string $operator): bool\n{\n    return in_array($operator, VALID_OPERATORS, true);\n}\n\n// before writing/generating config:\nif (!validPhpVersionOperator($cfg['operator'])) {\n    throw new InvalidArgumentException('phpVersionOperator must be a version_compare() operator');\n}","typeGuard":"/**\n * @param string $operator\n * @return '!='|'<'|'<='|'<>'|'='|'=='|'>'|'>='|'eq'|'ge'|'gt'|'le'|'lt'|'ne'\n */\nfunction narrowVersionOperator(string $operator): string\n{\n    return in_array($operator, ['!=', '<', '<=', '<>', '=', '==', '>', '>=', 'eq', 'ge', 'gt', 'le', 'lt', 'ne'], true)\n        ? $operator\n        : throw new InvalidArgumentException(\"Invalid version comparison operator: {$operator}\");\n}","tryCatchPattern":"try {\n    $configuration = (new \\PHPUnit\\TextUI\\XmlConfiguration\\Loader)->loadFile('phpunit.xml');\n} catch (\\PHPUnit\\TextUI\\XmlConfiguration\\Exception $e) {\n    if (str_contains($e->getMessage(), 'Invalid version comparison operator')) {\n        // fix the phpVersionOperator attribute to a version_compare() operator\n    }\n}","preventionTips":["phpVersionOperator uses version_compare() syntax, not composer semver: no ^, ~, or =~","When generating phpunit.xml programmatically, whitelist the 14 valid operators","Prefer the word forms (gte-style: ge, gt, le, lt, eq, ne) if unsure about XML escaping of < and >"],"tags":["phpunit","xml","version-constraint","configuration","phpversion"],"backgroundTag":"invalid-version-constraint","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}