rectorphp/rector · error · InvalidConfigurationException
The "%s" rule requires configuration.
Error message
The "%s" rule requires configuration.
What it means
AnnotationToAttributeRector is an active, configurable PHP 8.0 rule that rewrites docblock/Doctrine annotations into native attributes (e.g. @Route to #[Route]). It implements ConfigurableRectorInterface and its refactor() first checks the $annotationsToAttributes array (rules/Php80/Rector/Class_/AnnotationToAttributeRector.php:155); when that array is empty the rule was registered without its required configuration and it throws Rector\Exception\Configuration\InvalidConfigurationException. The throw happens while visiting any Class_, Property, Param, ClassMethod, Function_, Closure, ArrowFunction or Interface_ node.
Source
Thrown at rules/Php80/Rector/Class_/AnnotationToAttributeRector.php:156
}
}
CODE_SAMPLE
, [new AnnotationToAttribute('Symfony\Component\Routing\Annotation\Route')])]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Class_::class, Property::class, Param::class, ClassMethod::class, Function_::class, Closure::class, ArrowFunction::class, Interface_::class];
}
/**
* @param Class_|Property|Param|ClassMethod|Function_|Closure|ArrowFunction|Interface_ $node
*/
public function refactor(Node $node): ?Node
{
if ($this->annotationsToAttributes === []) {
throw new InvalidConfigurationException(sprintf('The "%s" rule requires configuration.', self::class));
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($node);
if (!$phpDocInfo instanceof PhpDocInfo) {
return null;
}
$uses = $this->useImportsResolver->resolveBareUses();
// 1. Doctrine annotation classes
$annotationAttributeGroups = $this->processDoctrineAnnotationClasses($phpDocInfo, $uses);
// 2. bare tags without annotation class, e.g. "@require"
$genericAttributeGroups = $this->processGenericTags($phpDocInfo);
$attributeGroups = array_merge($annotationAttributeGroups, $genericAttributeGroups);
if ($attributeGroups === []) {
return null;
}
// 3. Reprint docblock
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node);
$this->attributeGroupNamedArgumentManipulator->decorate($attributeGroups);
$node->attrGroups = array_merge($node->attrGroups, $attributeGroups);View on GitHub (pinned to 408fcb0ff1)
Solutions
- Configure the rule: ->withConfiguredRule(AnnotationToAttributeRector::class, [new AnnotationToAttribute('Symfony\Component\Routing\Annotation\Route'), ...]) with one AnnotationToAttribute entry per annotation class to convert.
- If the rule was enabled by mistake, remove it from withRules() entirely.
- Verify each mapped annotation class really is declared as an attribute class in the target dependency - the rule uses reflectionProvider->hasClass()/isAttributeClass() and silently skips classes that do not qualify, which can look like 'no configuration'.
Example fix
// before
use Rector\Php80\Rector\Class_\AnnotationToAttributeRector;
return RectorConfig::configure()
->withRules([AnnotationToAttributeRector::class]);
// after
use Rector\Php80\Rector\Class_\AnnotationToAttributeRector;
use Rector\Php80\ValueObject\AnnotationToAttribute;
return RectorConfig::configure()
->withConfiguredRule(AnnotationToAttributeRector::class, [
new AnnotationToAttribute('Symfony\Component\Routing\Annotation\Route'),
]); Defensive patterns
Strategy: validation
Validate before calling
use Rector\Php80\ValueObject\AnnotationToAttribute;
$annotationsToAttributes = [
new AnnotationToAttribute('Symfony\Component\Routing\Annotation\Route'),
];
if ($annotationsToAttributes === []) {
throw new InvalidArgumentException('AnnotationToAttributeRector requires at least one AnnotationToAttribute entry');
}
return RectorConfig::configure()
->withConfiguredRule(AnnotationToAttributeRector::class, $annotationsToAttributes); Type guard
$ruleReflection = new ReflectionClass($ruleClass); $needsConfiguration = $ruleReflection->implementsInterface(\Rector\Contract\Rector\ConfigurableRectorInterface::class); // if true: register with ->withConfiguredRule($ruleClass, $config), never with ->withRules()
Try / catch
try {
exit($rectorApplication->run());
} catch (\Rector\Exception\Configuration\InvalidConfigurationException $e) {
fwrite(STDERR, 'Rector config error: ' . $e->getMessage() . PHP_EOL);
fwrite(STDERR, 'Use ->withConfiguredRule() with an AnnotationToAttribute[] list.' . PHP_EOL);
exit(1);
} Prevention
- Register every rule implementing ConfigurableRectorInterface with ->withConfiguredRule(), not ->withRules().
- Keep the annotation map in a named $annotationsToAttributes variable and assert it is non-empty before wiring it in.
- Run vendor/bin/rector --dry-run in CI after any rector.php edit to surface configuration errors before a full run.
- Confirm each mapped annotation class is #[Attribute]-marked in the dependency; rector skips non-attribute classes via isAttributeClass().
When it happens
Trigger: Registering the rule without a mapping: ->withRules([AnnotationToAttributeRector::class]) instead of ->withConfiguredRule(AnnotationToAttributeRector::class, [new AnnotationToAttribute('Symfony\Component\Routing\Annotation\Route')]), or passing an empty array as the configuration. The exception is raised on the first matching node with a docblock that rector processes.
Common situations: Copy-pasting a config snippet that omits the second argument of withConfiguredRule(); migrating an old YAML container config where the annotation list was wired via a setter call; refactoring rector.php and accidentally dropping the AnnotationToAttribute entries.
Related errors
- "%s" rule is deprecated, as removing an annotation by name i
- "%s" rule is deprecated, as the #[Deprecated] attribute trig
- "%s" rule is deprecated, as the #[Deprecated] attribute trig
- "%s" rule is deprecated, as turning a docblock type into a r
- "%s" rule is deprecated, as risky. The "??" and "?:" operato
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/7146a2b5c023b294.
Report an issue: GitHub.