rectorphp/rector · error · RectorRuleNotFoundException

Rule "%s" was not found.%sThe rule has no namespace. Make su

Error message

Rule "%s" was not found.%sThe rule has no namespace. Make sure to escape the backslashes, and add quotes around the rule name: --only="My\Rector\Rule"

What it means

If the --only value contains no backslash at all, the shell has likely eaten the namespace separators (e.g. --only=\Rector\Some\Rule collapsing to RectorSomeRule after double-quote processing or Windows quoting). OnlyRuleResolver then throws RectorRuleNotFoundException explaining the value has no namespace and shows the correct quoting form. The resolver even tries a backslash-stripped comparison first, so reaching this error means that also found nothing.

Source

Thrown at src/Configuration/OnlyRuleResolver.php:77

            $flattenMatching = [];
            foreach ($this->rectors as $rector) {
                if (str_replace('\\', '', get_class($rector)) === $rule) {
                    $flattenMatching[] = get_class($rector);
                }
            }
            $flattenMatching = array_unique($flattenMatching);
            if (count($flattenMatching) === 1) {
                return $flattenMatching[0];
            }
            $message = sprintf('Rule "%s" was not found.%sThe rule has no namespace. Make sure to escape the backslashes, and add quotes around the rule name: --only="My\Rector\Rule"', $rule, \PHP_EOL);
        } else {
            // the rule class exists, it is just missing in the config
            if ($this->isRectorRuleClass($rule)) {
                throw new RectorRuleNotFoundException($this->createUnregisteredMessage($rule));
            }
            $message = sprintf('Rule "%s" was not found.%sMake sure it is registered in your config or in one of the sets', $rule, \PHP_EOL);
        }
        throw new RectorRuleNotFoundException($message);
    }
    /**
     * Is this an existing rule class, that is just not registered in the config?
     */
    private function isRectorRuleClass(string $className): bool
    {
        if (!class_exists($className)) {
            return \false;
        }
        $reflectionClass = new ReflectionClass($className);
        if ($reflectionClass->isAbstract()) {
            return \false;
        }
        return $reflectionClass->implementsInterface(RectorInterface::class);
    }
    private function createUnregisteredMessage(string $ruleClass): string
    {
        $shortRuleClass = (string) substr((string) strrchr($ruleClass, '\\'), 1);

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Quote the argument exactly as the message shows: --only="My\Rector\Rule" (double quotes on Unix shells)
  2. In CI YAML, prefer single-quoted YAML scalars so backslashes survive: '--only="My\Rector\Rule"'
  3. Alternatively avoid shell entirely: put the rule in withRules() and run without --only

Example fix

# before: unquoted backslashes get eaten by the shell
vendor/bin/rector process src --only=Rector\Php81\Rector\Property\ReadOnlyPropertyRector

# after: quote the whole class name
vendor/bin/rector process src --only="Rector\Php81\Rector\Property\ReadOnlyPropertyRector"
Defensive patterns

Strategy: validation

Validate before calling

// wrapper-side check before invoking rector
$only = (string) getopt('', ['only:'])['only'] ?? '';
if (strpos($only, '\\') !== false || (strpos($only, '\') === false && preg_match('/^[A-Z]/', $only))) {
    fwrite(STDERR, "--only needs a quoted FQCN, e.g. --only=\"My\\Rector\\Rule\"\n");
}

Type guard

function isWellFormedRuleName(string $rule): bool
{
    return strpos($rule, '\\') === false && strpos($rule, '\') !== false;
}

Try / catch

catch \Rector\Exception\Configuration\RectorRuleNotFoundException; if the message says 'The rule has no namespace', re-run with the value double-quoted: --only="My\Rector\Rule".

Prevention

When it happens

Trigger: Passing --only=Rector\Php81\Rector\FuncCall\ReadOnlyPropertyRector without quotes so the shell strips \R etc.; Windows cmd single-quoting artifacts (leading/trailing quotes are stripped automatically, but mangled separators are not); double-escaped \\ inputs on exotic shells.

Common situations: Copy-pasting a FQCN from docs into a bash/zsh command without wrapping it in quotes; CI YAML where backslashes need careful escaping; PowerShell mangling backslashes.

Related errors


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