rectorphp/rector · error · ShouldNotHappenException

"%s" rule is deprecated, as matching sensitive parameters by

Error message

"%s" rule is deprecated, as matching sensitive parameters by name is vague and risky. Add the #[\SensitiveParameter] attribute per case instead

What it means

Rector\Php82\Rector\Param\AddSensitiveParameterAttributeRector is deprecated: refactor() unconditionally throws Rector\Exception\ShouldNotHappenException on the first Param node it visits. The rule used to add the #[\SensitiveParameter] attribute to parameters matched by configured names (e.g. 'password'), but matching secrets by name alone is vague and risky - it can flag unrelated parameters that happen to share a name. Its configure() body is now an empty no-op, so any old configuration passed via withConfiguredRule() is silently discarded before the exception is thrown.

Source

Thrown at rules/Php82/Rector/Param/AddSensitiveParameterAttributeRector.php:41

     * @var string
     */
    public const SENSITIVE_PARAMETERS = 'sensitive_parameters';
    /**
     * @param array<string, mixed> $configuration
     */
    public function configure(array $configuration): void
    {
    }
    public function getNodeTypes(): array
    {
        return [Param::class];
    }
    /**
     * @param Node\Param $node
     */
    public function refactor(Node $node): ?Param
    {
        throw new ShouldNotHappenException(sprintf('"%s" rule is deprecated, as matching sensitive parameters by name is vague and risky. Add the #[\SensitiveParameter] attribute per case instead', self::class));
    }
    public function getRuleDefinition(): RuleDefinition
    {
        return new RuleDefinition('Add SensitiveParameter attribute to method and function configured parameters', [new ConfiguredCodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
    public function run(string $password)
    {
    }
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
    public function run(#[\SensitiveParameter] string $password)
    {
    }
}

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Remove AddSensitiveParameterAttributeRector from rector.php - it no longer adds anything.
  2. Add #[\SensitiveParameter] by hand to each parameter that genuinely carries a secret (token, password, private key), reviewing each call site.
  3. If you have many occurrences, write a small custom rule scoped to the exact services/parameters that handle secrets.
  4. Temporary stopgap only: pin the last rector version shipping the working rule, and schedule config cleanup.

Example fix

// before (rector.php)
->withConfiguredRule(AddSensitiveParameterAttributeRector::class, [
    'password', 'secret',
])

// after (rector.php) - entry deleted

// before (src/Auth.php)                 // after (src/Auth.php)
public function login(string $password)   public function login(#[\SensitiveParameter] string $password)
Defensive patterns

Strategy: validation

Validate before calling

use Rector\Php82\Rector\Param\AddSensitiveParameterAttributeRector;

$rules = [/* your list */ AddSensitiveParameterAttributeRector::class];
if (in_array(AddSensitiveParameterAttributeRector::class, $rules, true)) {
    throw new InvalidArgumentException('AddSensitiveParameterAttributeRector is deprecated; add #[\SensitiveParameter] manually instead');
}

Try / catch

try {
    exit($rectorApplication->run());
} catch (\Rector\Exception\ShouldNotHappenException $e) {
    if (str_contains($e->getMessage(), 'AddSensitiveParameterAttributeRector')) {
        fwrite(STDERR, 'Remove the deprecated rule from rector.php and mark secrets manually.' . PHP_EOL);
        exit(1);
    }
    throw $e;
}

Prevention

When it happens

Trigger: The rule is still referenced in rector.php (withRules() or withConfiguredRule() with the old parameter-name list) and rector processes any function/method parameter; refactor() throws on the first Param node regardless of configuration.

Common situations: Upgrading rector after this PHP 8.2 rule was gutted; security-check CI configs copied from older blog posts that still list the rule; assuming the old 'password'/'secret' name configuration still works because no config error is reported at load time.

Related errors


AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21). Data as JSON: /api/errors/5c2003a641abe1bc. Report an issue: GitHub.