{"record":{"id":"e3b504dd9c691285","repo":"rectorphp/rector","slug":"your-config-already-enables-s-set-sremove-s","errorCode":null,"errorMessage":"Your config already enables %s set.%sRemove \"->%s()\" as it only duplicates it, or remove %s set.","messagePattern":"Your config already enables (.+?) set\\.(.+?)Remove \"->(.+?)\\(\\)\" as it only duplicates it, or remove (.+?) set\\.","errorType":"exception","errorClass":"InvalidConfigurationException","httpStatus":null,"severity":"error","filePath":"src/Configuration/RectorConfigBuilder.php","lineNumber":188,"sourceCode":"            $this->sets[] = SetList::PHP_POLYFILLS;\n        }\n        if ($this->pickedPhpSetsVersion !== null) {\n            SimpleParameterProvider::setParameter(\\Rector\\Configuration\\Option::POLYFILL_CEILING_PHP_VERSION, $this->pickedPhpSetsVersion);\n        }\n        // merge sets together\n        $this->sets = array_merge($this->sets, $this->groupLoadedSets);\n        $uniqueSets = array_unique($this->sets);\n        if ($this->isWithPhpLevelUsed && $this->isWithPhpSetsUsed) {\n            throw new InvalidConfigurationException(sprintf('Your config uses \"withPhp*()\" and \"withPhpLevel()\" methods at the same time.%sPick one of them to avoid rule conflicts.', \\PHP_EOL));\n        }\n        foreach (self::LEVEL_METHOD_TO_SET as $levelMethod => [$setFilePath, $setTitle]) {\n            if (!isset($this->usedLevelMethods[$levelMethod])) {\n                continue;\n            }\n            if (!in_array($setFilePath, $uniqueSets, \\true)) {\n                continue;\n            }\n            throw new InvalidConfigurationException(sprintf('Your config already enables %s set.%sRemove \"->%s()\" as it only duplicates it, or remove %s set.', $setTitle, \\PHP_EOL, $levelMethod, $setTitle));\n        }\n        if ($uniqueSets !== []) {\n            $rectorConfig->sets($uniqueSets);\n        }\n        // log rules from sets and compare them with explicit rules\n        $setRegisteredRectorClasses = $rectorConfig->getMainRectorClasses();\n        SimpleParameterProvider::addParameter(\\Rector\\Configuration\\Option::SET_REGISTERED_RULES, $setRegisteredRectorClasses);\n        if ($this->paths !== []) {\n            $rectorConfig->paths($this->paths);\n        }\n        // must be in upper part, as these services might be used by rule registered bellow\n        foreach ($this->registerServices as $registerService) {\n            $rectorConfig->singleton($registerService->getClassName());\n            if ($registerService->getAlias()) {\n                $rectorConfig->alias($registerService->getClassName(), $registerService->getAlias());\n            }\n            if ($registerService->getTag()) {\n                $rectorConfig->tag($registerService->getClassName(), $registerService->getTag());","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/rectorphp/rector/blob/408fcb0ff1833e3d26cbc9b04c23a77565814a16/src/Configuration/RectorConfigBuilder.php#L170-L206","documentation":"Besides the withPhp*() guard, RectorConfigBuilder maps each level method (withTypeCoverageLevel, withTypeCoverageDocblockLevel, withDeadCodeLevel, withCodeQualityLevel, withCodingStyleLevel) to the set it implicitly enables. If you both call a level method and load the same set (e.g. via withSets([SetList::DEAD_CODE]) or importing the set file), it throws InvalidConfigurationException naming both the method and the set, since the rules would run twice.","triggerScenarios":"rector.php containing ->withDeadCodeLevel(20) together with ->withSets([SetList::DEAD_CODE]), or the same duplication for type declarations / code quality / coding style sets.","commonSituations":"Configs assembled from older examples that manually imported sets plus newer snippets using the level builder methods; enabling 'dead-code' via a Symfony-ish bundle config and also via the builder.","solutions":["Remove the explicit set: drop ->withSets([SetList::DEAD_CODE]) and keep ->withDeadCodeLevel(20)","Or drop the level method and keep the set import -- the exception message names both so delete exactly one side","Audit rector.php for every SetList::* constant that overlaps a with*Level() call"],"exampleFix":"// before\nreturn RectorConfig::configure()\n    ->withSets([SetList::DEAD_CODE])\n    ->withDeadCodeLevel(20);\n\n// after\nreturn RectorConfig::configure()\n    ->withDeadCodeLevel(20);","handlingStrategy":"validation","validationCode":"// lint: a level method plus its matching SetList constant is a duplicate\n$config = file_get_contents('rector.php');\n$duplicates = [\n    'withDeadCodeLevel' => 'SetList::DEAD_CODE',\n    'withCodeQualityLevel' => 'SetList::CODE_QUALITY',\n    'withCodingStyleLevel' => 'SetList::CODING_STYLE',\n    'withTypeCoverageLevel' => 'SetList::TYPE_DECLARATION',\n];\nforeach ($duplicates as $method => $set) {\n    if (strpos($config, $method) !== false && strpos($config, $set) !== false) {\n        fwrite(STDERR, \"Duplicate enablement: {$method} + {$set}\\n\");\n    }\n}","typeGuard":null,"tryCatchPattern":"catch \\Rector\\Exception\\Configuration\\InvalidConfigurationException; parse the set title and method name from the message and remove one side, then re-load the config.","preventionTips":["Enable a domain exactly once: either the with*Level() method or the SetList entry, never both","Review imports in rector.php for set files that overlap builder methods","Keep configs small and re-run `rector init` diff after major upgrades to adopt current idioms"],"tags":["php","rector","config","duplicate","sets","level"],"backgroundTag":"duplicate-config-entries","analyzedSha":"408fcb0ff1833e3d26cbc9b04c23a77565814a16","analyzedAt":"2026-08-21T05:11:02.643Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}