rectorphp/rector · error · ShouldNotHappenException
"%s" is deprecated, as the pipe chain length that stays read
Error message
"%s" is deprecated, as the pipe chain length that stays readable depends on the context of surrounding code
What it means
Rector\Php85\Rector\Expression\NestedFuncCallsToPipeOperatorRector is deprecated: refactor() throws Rector\Exception\ShouldNotHappenException on the first Expression or Return_ node. The rule rewrote nested calls like strtolower(trim($s)) into PHP 8.5 pipe chains, but how long a chain stays readable depends entirely on the surrounding code, so the old MINIMUM_DEPTH threshold (default 3, shown in the rule's own configured code sample) cannot be a safe default. The rule only loads on PhpVersionFeature::PIPE_OPERATOER (PHP 8.5) targets.
Source
Thrown at rules/Php85/Rector/Expression/NestedFuncCallsToPipeOperatorRector.php:67
$result = $input
|> htmlspecialchars(...)
|> strtolower(...)
|> trim(...);
}
}
CODE_SAMPLE
, [self::MINIMUM_DEPTH => 3])]);
}
public function getNodeTypes(): array
{
return [Expression::class, Return_::class];
}
/**
* @param Expression|Return_ $node
*/
public function refactor(Node $node): ?Node
{
throw new ShouldNotHappenException(sprintf('"%s" is deprecated, as the pipe chain length that stays readable depends on the context of surrounding code', self::class));
}
public function provideMinPhpVersion(): int
{
return PhpVersionFeature::PIPE_OPERATOER;
}
}
View on GitHub (pinned to 408fcb0ff1)
Solutions
- Remove NestedFuncCallsToPipeOperatorRector from rector.php.
- Rewrite specific hot spots into pipe chains by hand where the chain actually improves readability.
- If your team has a hard style rule, encode it in a custom rule scoped to your codebase instead of re-enabling this one.
Example fix
// before (rector.php)
->withConfiguredRule(NestedFuncCallsToPipeOperatorRector::class, [
NestedFuncCallsToPipeOperatorRector::MINIMUM_DEPTH => 3,
])
// after (rector.php) - removed; convert by hand where it reads better
// manual (PHP 8.5):
$name = $input |> trim(...) |> strtolower(...); Defensive patterns
Strategy: validation
Validate before calling
use Rector\Php85\Rector\Expression\NestedFuncCallsToPipeOperatorRector;
$rules = [/* your list */ NestedFuncCallsToPipeOperatorRector::class];
if (in_array(NestedFuncCallsToPipeOperatorRector::class, $rules, true)) {
throw new InvalidArgumentException('Rule deprecated; write pipe chains manually where readability improves');
} Try / catch
try {
exit($rectorApplication->run());
} catch (\Rector\Exception\ShouldNotHappenException $e) {
if (str_contains($e->getMessage(), 'NestedFuncCallsToPipeOperator')) {
fwrite(STDERR, 'Remove the rule; chain length is a per-case readability judgement, not a fixed threshold.' . PHP_EOL);
exit(1);
}
throw $e;
} Prevention
- Do not rely on the old MINIMUM_DEPTH setting - the rule ignores configuration and throws regardless.
- Adopt new syntax like the pipe operator through reviewed manual edits, not bulk rewrites.
- Track rector release notes for PHP 8.5 rules before enabling a copied 'modernize' config.
When it happens
Trigger: The rule is still listed in a PHP 8.5 rule list and rector visits any expression statement or return statement; refactor() throws on the first match, even if the old MINIMUM_DEPTH configuration was passed (it is ignored).
Common situations: Enabling all Php85 rules after a rector upgrade; configs copied from pipe-operator announcement posts; CI failing on the very first analyzed statement.
Related errors
- "%s" is deprecated, as it removes intermediate variables tha
- "%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
- "%s" rule is deprecated, as it is a personal preference that
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/018b9db63796a376.
Report an issue: GitHub.