rectorphp/rector · error · ShouldNotHappenException
Rector name cannot be empty
Error message
Rector name cannot be empty
What it means
The custom-rule console command interactively asks for the rule class name using SymfonyStyle::ask() with a validator closure. The closure throws ShouldNotHappenException('Rector name cannot be empty') when the answer is null (Ctrl+C style abort) or an empty string, so the scaffold command refuses to generate files for an unnamed rule.
Source
Thrown at src/Console/Command/CustomRuleCommand.php:44
*/
private ReflectionProvider $reflectionProvider;
public function __construct(SymfonyStyle $symfonyStyle, ReflectionProvider $reflectionProvider)
{
$this->symfonyStyle = $symfonyStyle;
$this->reflectionProvider = $reflectionProvider;
parent::__construct();
}
protected function configure(): void
{
$this->setName('custom-rule');
$this->setDescription('Create base of local custom rule with tests');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
// ask for rule name
$rectorName = $this->symfonyStyle->ask('What is the rule class name? (e.g. "LegacyCallToDbalMethodCall")?', null, static function (?string $answer): string {
if ($answer === '' || $answer === null) {
throw new ShouldNotHappenException('Rector name cannot be empty');
}
return $answer;
});
// suffix with Rector by convention
if (substr_compare((string) $rectorName, 'Rector', -strlen('Rector')) !== 0) {
$rectorName .= 'Rector';
}
$rectorName = ucfirst((string) $rectorName);
// find all files in templates directory
$finder = Finder::create()->files()->in(__DIR__ . '/../../../templates/custom-rule')->notName('__Name__Test.php.phtml');
// 0. resolve if local phpunit is at least PHPUnit 10 (which supports #[DataProvider])
// to provide annotation if not
if ($this->isPHPUnitAttributeSupported()) {
$finder->append([new SplFileInfo(__DIR__ . '/../../../templates/custom-rule/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml', 'utils/rector/tests/Rector/__Name__', 'utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml')]);
} else {
// use @annotations for PHPUnit 9 and bellow
$finder->append([new SplFileInfo(__DIR__ . '/../../../templates/custom-rules-annotations/utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml', 'utils/rector/tests/Rector/__Name__', 'utils/rector/tests/Rector/__Name__/__Name__Test.php.phtml')]);
}View on GitHub (pinned to 408fcb0ff1)
Solutions
- Re-run vendor/bin/rector custom-rule and type a non-empty class name, e.g. LegacyCallToDbalMethodCall (the 'Rector' suffix is appended automatically if missing)
- When scripting, pipe the name in: echo 'MyRule' | vendor/bin/rector custom-rule
- Do not abort at the prompt with empty input; use Ctrl+C to cancel intentionally
Example fix
// before (interactive session) $ vendor/bin/rector custom-rule What is the rule class name? => <Enter> // throws // after $ vendor/bin/rector custom-rule What is the rule class name? => LegacyCallToDbalMethodCall
Defensive patterns
Strategy: validation
Validate before calling
// pre-validate before driving the command non-interactively
$ruleName = trim((string) $input->getOption('rule-name'));
if ($ruleName === '') {
throw new RuntimeException('Rule name is required when running custom-rule non-interactively.');
}
shell_exec(sprintf('echo %s | vendor/bin/rector custom-rule', escapeshellarg($ruleName))); Type guard
function isValidRuleClassName(string $name): bool
{
return preg_match('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/', $name) === 1;
} Prevention
- Provide the name up front when scripting instead of relying on the interactive prompt
- Type the class in StudlyCase; the command appends the Rector suffix automatically
- Do not run interactive scaffold commands in CI stages without piped input
When it happens
Trigger: Running vendor/bin/rector custom-rule and pressing Enter on the 'What is the rule class name?' prompt without typing anything; or piping empty stdin in a non-interactive script.
Common situations: Running the command in CI or a scripted pipeline with no TTY where ask() receives empty input; accidentally hitting Enter twice; automating scaffolds with expect and mis-timing the answer.
Related errors
- [parallel] Main script was not found
- Short rule name "%s" is ambiguous. Specify the full rule nam
- Rule "%s" exists, but is not registered in your Rector confi
- Rule "%s" was not found.%sThe rule has no namespace. Make su
- Rule "%s" was not found.%sMake sure it is registered in your
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/24be96c34c96b97d.
Report an issue: GitHub.