{"record":{"id":"3f462b5836c4e926","repo":"rectorphp/rector","slug":"set-provider-s-must-implement-s","errorCode":null,"errorMessage":"Set provider \"%s\" must implement \"%s\"","messagePattern":"Set provider \"(.+?)\" must implement \"(.+?)\"","errorType":"exception","errorClass":"InvalidConfigurationException","httpStatus":null,"severity":"error","filePath":"src/Configuration/RectorConfigBuilder.php","lineNumber":807,"sourceCode":"        $this->reportUnusedSkips = $report;\n        return $this;\n    }\n    public function withEditorUrl(string $editorUrl): self\n    {\n        $this->editorUrl = $editorUrl;\n        return $this;\n    }\n    /**\n     * @param class-string<SetProviderInterface> ...$setProviders\n     */\n    public function withSetProviders(string ...$setProviders): self\n    {\n        foreach ($setProviders as $setProvider) {\n            if (\\array_key_exists($setProvider, $this->setProviders)) {\n                continue;\n            }\n            if (!is_a($setProvider, SetProviderInterface::class, \\true)) {\n                throw new InvalidConfigurationException(sprintf('Set provider \"%s\" must implement \"%s\"', $setProvider, SetProviderInterface::class));\n            }\n            $this->setProviders[$setProvider] = \\true;\n        }\n        return $this;\n    }\n    /**\n     * @param PhpVersion::* $phpVersion\n     */\n    private function addPhpLevelSets(int $phpVersion): self\n    {\n        $this->isWithPhpSetsUsed = \\true;\n        $this->sets = array_merge($this->sets, \\Rector\\Configuration\\PhpLevelSetResolver::resolveFromPhpVersion($phpVersion));\n        return $this;\n    }\n    private function reportDeprecatedPhpSetsMethod(string $methodName): self\n    {\n        SimpleParameterProvider::addParameter(\\Rector\\Configuration\\Option::DEPRECATED_PHP_SETS_METHODS, $methodName);\n        return $this;","sourceCodeStart":789,"sourceCodeEnd":825,"githubUrl":"https://github.com/rectorphp/rector/blob/408fcb0ff1833e3d26cbc9b04c23a77565814a16/src/Configuration/RectorConfigBuilder.php#L789-L825","documentation":"RectorConfigBuilder::withSetProviders(string ...$setProviders) registers classes that supply extra rule sets. Each class-string is verified with is_a($setProvider, SetProviderInterface::class, true); a class that does not implement Rector\\Set\\SetProviderInterface throws InvalidConfigurationException naming the offending class and the required interface.","triggerScenarios":"Passing a FQCN that is not a SetProviderInterface implementation: a typo'd namespace, a plain value object, or a SetList constant instead of a provider class. Also triggered by passing a class that only extends a base class without implementing the interface.","commonSituations":"Copy-pasting a SetList:: constant into withSetProviders(); fat-fingered namespaces after renaming vendor packages; passing an instance or ::class of an unrelated helper while wiring custom sets.","solutions":["Open the class named in the message and make it implement Rector\\Set\\SetProviderInterface with a sets() method returning Rector\\Set\\ValueObject\\Set[] instances","Fix the namespace/typo so the string matches the real provider class","If you meant a built-in set, use withSets([SomeSetList::CONSTANT]) instead of withSetProviders()","Pass class-strings via SomeProvider::class, never literals or objects"],"exampleFix":"// before\nreturn $this->withSetProviders('App\\Support\\ProjectSetList');\n\n// after\nfinal class ProjectSetProvider implements \\Rector\\Set\\SetProviderInterface\n{\n    /**\n     * @return Set[]\n     */\n    public function sets(): array\n    {\n        return [new Set('project-conventions', [SomeRule::class])];\n    }\n}\n\nreturn $this->withSetProviders(ProjectSetProvider::class);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"/** @param class-string ...$providers */\nfunction assertSetProviders(string ...$providers): void\n{\n    foreach ($providers as $provider) {\n        if (! is_a($provider, \\Rector\\Set\\SetProviderInterface::class, true)) {\n            throw new InvalidArgumentException(sprintf('%s does not implement SetProviderInterface', $provider));\n        }\n    }\n}","tryCatchPattern":"try {\n    $builder->withSetProviders(ProjectSetProvider::class);\n} catch (InvalidConfigurationException $e) {\n    // message names the class and the interface; fix the class-string, not the call\n    $logger->error($e->getMessage());\n}","preventionTips":["Always pass SomeProvider::class so the IDE resolves and refactors the symbol","Keep one interface-ful provider per package and register it via composer extra or your bootstrap, not ad-hoc strings","Run a static analyzer (PHPStan) with is-a checks so wrong class-strings fail in CI, not at runtime"],"tags":["php","rector","config","set-provider","interface-check"],"backgroundTag":"class-missing-interface","analyzedSha":"408fcb0ff1833e3d26cbc9b04c23a77565814a16","analyzedAt":"2026-08-21T05:11:02.643Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}