rectorphp/rector · error · ShouldNotHappenException
"%s" is deprecated as depends on context and personal prefer
Error message
"%s" is deprecated as depends on context and personal preference, hard to generalize. Handle it manually or via a custom rule instead
What it means
JoinStringConcatRector used to merge chained string concatenations like 'a' . 'b' . $c into fewer parts. It is deprecated because whether joined strings read better is a matter of context and personal taste that cannot be generalized, so refactor() now throws ShouldNotHappenException for every Concat node. The rule performs no work anymore; the exception exists purely to make stale configs fail fast.
Source
Thrown at rules/CodeQuality/Rector/Concat/JoinStringConcatRector.php:52
$name = 'Hi Tom';
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Concat::class];
}
/**
* @param Concat $node
*/
public function refactor(Node $node): ?Node
{
throw new ShouldNotHappenException(sprintf('"%s" is deprecated as depends on context and personal preference, hard to generalize. Handle it manually or via a custom rule instead', self::class));
}
}
View on GitHub (pinned to 408fcb0ff1)
Solutions
- Remove JoinStringConcatRector::class from rector.php and any imported set files, then re-run vendor/bin/rector dry-run
- If you want constant-string folding, handle the few occurrences manually or with a targeted script
- If join style matters to your team, encode it in a coding-standard tool (PHP-CS-Fixer) rather than Rector
- grep -r JoinStringConcatRector across the project to find every registration point
Example fix
// before (rector.php)
->withRules([
\Rector\CodeQuality\Rector\Concat\JoinStringConcatRector::class,
])
// after
->withRules([
// keep only non-deprecated CodeQuality rules here
])
// manually: echo 'Hello' . ' ' . 'world'; -> echo 'Hello world'; Defensive patterns
Strategy: validation
Validate before calling
$deprecated = ['JoinStringConcatRector'];
foreach (glob(__DIR__ . '/rector*.php') as $config) {
$src = file_get_contents($config);
foreach ($deprecated as $rule) {
if (str_contains($src, $rule)) {
fwrite(STDERR, "Remove deprecated rule {$rule} from {$config}\n");
exit(1);
}
}
} Prevention
- Treat string-joining style as a coding-standard concern, not a Rector concern
- Audit imported set packages for deprecated rule names after each upgrade
- Use dry-run on one directory first to catch deprecation guards early
- Remove rules you do not actively need instead of carrying a maximal whitelist
When it happens
Trigger: Having rules/CodeQuality/Rector/Concat/JoinStringConcatRector.php registered (directly or via a set) and running rector over any file containing a string concatenation expression (. operator). The first Concat node visited triggers the throw at rules/CodeQuality/Rector/Concat/JoinStringConcatRector.php:52.
Common situations: An old rector.php with a hand-picked CodeQuality rule list, or a shared company-wide set package, still contains JoinStringConcatRector after upgrading Rector. The crash appears the moment dry-run touches any file with 'literal' . 'literal' concatenation, which is extremely common, so it fails almost immediately.
Related errors
- "%s" rule is deprecated, as it is a personal preference that
- "%s" is deprecated, as simplifying regex ranges is a persona
- "%s" rule is deprecated, as it is a personal preference that
- "%s" rule is deprecated, as it covers a very specific shape
- "%s" is deprecated as noisy change with little value. Use ma
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/e95383b874404656.
Report an issue: GitHub.