rectorphp/rector · error · ShouldNotHappenException

"%s" rule is deprecated, as the param type guessed from a si

Error message

"%s" rule is deprecated, as the param type guessed from a single array_map() closure is vague and unreliable. Add the @param docblock manually instead

What it means

Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddParamArrayDocblockBasedOnArrayMapRector is deprecated: refactor() throws Rector\Exception\ShouldNotHappenException on the first ClassMethod or Function_ node. The rule guessed a @param array<...> docblock for parameters consumed by a single array_map() closure, but a type inferred from one usage site is vague and unreliable as a contract for the whole parameter.

Source

Thrown at rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockBasedOnArrayMapRector.php:56

        $names = array_map(fn(string $name) => trim($name), $names);
    }
}
CODE_SAMPLE
)]);
    }
    /**
     * @return array<class-string<Node>>
     */
    public function getNodeTypes(): array
    {
        return [ClassMethod::class, Function_::class];
    }
    /**
     * @param ClassMethod|Function_ $node
     */
    public function refactor(Node $node): ?Node
    {
        throw new ShouldNotHappenException(sprintf('"%s" rule is deprecated, as the param type guessed from a single array_map() closure is vague and unreliable. Add the @param docblock manually instead', self::class));
    }
}

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Remove AddParamArrayDocblockBasedOnArrayMapRector from rector.php.
  2. Write the @param docblock manually where the accepted shape is actually known (check the callers).
  3. Prefer native param types plus explicit generics in one reviewed place over generated guesses.

Example fix

// before (rector.php)
->withRules([AddParamArrayDocblockBasedOnArrayMapRector::class])

// after (rector.php) - removed; write by hand

/**
 * @param array<int, string> $names
 */
public function upperAll(array $names): array
Defensive patterns

Strategy: validation

Validate before calling

use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddParamArrayDocblockBasedOnArrayMapRector;

$rules = [/* your list */ AddParamArrayDocblockBasedOnArrayMapRector::class];
if (in_array(AddParamArrayDocblockBasedOnArrayMapRector::class, $rules, true)) {
    throw new InvalidArgumentException('Rule deprecated; write the @param docblock manually after checking callers');
}

Try / catch

try {
    exit($rectorApplication->run());
} catch (\Rector\Exception\ShouldNotHappenException $e) {
    if (str_contains($e->getMessage(), 'AddParamArrayDocblockBasedOnArrayMapRector')) {
        fwrite(STDERR, 'Remove the rule; a type guessed from one usage site is not a contract.' . PHP_EOL);
        exit(1);
    }
    throw $e;
}

Prevention

When it happens

Trigger: The rule is still referenced in a TypeDeclarationDocblocks rule list and rector visits any method or function; refactor() throws on the first match.

Common situations: Enabling all TypeDeclarationDocblocks rules to raise PHPStan coverage; CI failing at the first method after a rector upgrade; leftover configs from experiments with docblock generation.

Related errors


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