rectorphp/rector · error · ShouldNotHappenException
"%s" rule is deprecated, as a function call can rarely be tu
Error message
"%s" rule is deprecated, as a function call can rarely be turned to a method call without breaking the code; use a custom rule for the exact project case instead
What it means
Rector\Transform\Rector\FuncCall\FuncCallToMethodCallRector is deprecated: refactor() throws Rector\Exception\ShouldNotHappenException on the first Class_ node. The rule turned configured global function calls (e.g. some_helper()) into static or service method calls, but a function call can rarely be swapped for a method call without breaking code - the target object may not exist, names collide, and call semantics differ. configure() is a no-op now, so previously passed mappings are ignored.
Source
Thrown at rules/Transform/Rector/FuncCall/FuncCallToMethodCallRector.php:64
$this->someRenderer->view('...');
}
}
CODE_SAMPLE
, [new FuncCallToMethodCall('view', 'Namespaced\SomeRenderer', 'render')])]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
throw new ShouldNotHappenException(sprintf('"%s" rule is deprecated, as a function call can rarely be turned to a method call without breaking the code; use a custom rule for the exact project case instead', self::class));
}
/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
}
}
View on GitHub (pinned to 408fcb0ff1)
Solutions
- Remove FuncCallToMethodCallRector from rector.php.
- Do the function-to-method migration by hand per call site, verifying the receiver object is actually available there.
- If it is a standing project convention, write a custom rule scoped to the exact function/method pair.
Example fix
// before (rector.php)
->withConfiguredRule(FuncCallToMethodCallRector::class, [
'some_helper' => [SomeService::class, 'helper'],
])
// after (rector.php) - removed; migrate call sites by hand
// before // after
$value = some_helper(); $value = $this->someService->helper(); Defensive patterns
Strategy: validation
Validate before calling
use Rector\Transform\Rector\FuncCall\FuncCallToMethodCallRector;
$rules = [/* your list */ FuncCallToMethodCallRector::class];
if (in_array(FuncCallToMethodCallRector::class, $rules, true)) {
throw new InvalidArgumentException('Rule deprecated; migrate function calls manually or via a custom project rule');
} Try / catch
try {
exit($rectorApplication->run());
} catch (\Rector\Exception\ShouldNotHappenException $e) {
if (str_contains($e->getMessage(), 'FuncCallToMethodCallRector')) {
fwrite(STDERR, 'Remove the rule; function-to-method swaps need per-call-site verification.' . PHP_EOL);
exit(1);
}
throw $e;
} Prevention
- Migrate helper functions to service methods in reviewed commits where receiver availability is checked at each call site.
- Keep a shortlist of sanctioned custom rules in the repo instead of relying on generic Transform rules for API-shape changes.
- Drop deprecated Transform rules from rector.php during upgrade PRs rather than leaving them for CI to trip over.
When it happens
Trigger: The rule remains in rector.php (withRules() or withConfiguredRule() with an old function=>method map) and rector visits any class; refactor() throws on the first Class_ node.
Common situations: Old configs migrating helper functions to a service class; projects that wired e.g. env() or trans() helpers to method calls; CI failing after a rector upgrade that emptied the implementation.
Related errors
- "%s" rule is deprecated, as too niche; use a custom rule sco
- "%s" rule is deprecated, as the scalar value target is too w
- "%s" rule is deprecated, as turning a docblock type into a r
- "%s" rule is deprecated, as risky. The "??" and "?:" operato
- "%s" is deprecated as depends on context and personal prefer
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/48fd23dc2c36a6e6.
Report an issue: GitHub.