rectorphp/rector · error · ShouldNotHappenException
"%s" is deprecated as it has no real value
Error message
"%s" is deprecated as it has no real value
What it means
RemoveTypedPropertyNonMockDocblockRector used to remove docblocks like @var MockObject|MyClass duplicated on typed properties where the native type already carries the information. It is deprecated because the cleanup has no real value — modern tooling reads native types, and the rule's heuristic added churn without benefit. refactor() now throws ShouldNotHappenException on every Class_ node; the rule does no work.
Source
Thrown at rules/DeadCode/Rector/ClassLike/RemoveTypedPropertyNonMockDocblockRector.php:52
use PHPUnit\Framework\MockObject\MockObject;
final class SomeTest extends TestCase
{
private SomeClass $someProperty;
}
CODE_SAMPLE
)]);
}
public function getNodeTypes(): array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
throw new ShouldNotHappenException(sprintf('"%s" is deprecated as it has no real value', self::class));
}
}
View on GitHub (pinned to 408fcb0ff1)
Solutions
- Remove RemoveTypedPropertyNonMockDocblockRector::class from rector.php and all imported set files, then re-run vendor/bin/rector dry-run
- Leave redundant @var docblocks alone, or delete them opportunistically while editing each file
- If you want them gone now, run a scoped one-off script or IDE cleanup on the tests directory
- Check shared set bundles for lingering references to the rule name
Example fix
// before (rector.php)
->withRules([
\Rector\DeadCode\Rector\ClassLike\RemoveTypedPropertyNonMockDocblockRector::class,
])
// code:
class UserServiceTest extends TestCase {
/** @var UserService&MockObject */
private UserService $service;
}
// after (rector.php)
// rule removed; docblock left in place (it still aids IDE/PHPStan with union info) Defensive patterns
Strategy: validation
Validate before calling
$deprecated = ['RemoveTypedPropertyNonMockDocblockRector'];
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
- Keep informative @var MockObject unions — they aid IDE and PHPStan
- Remove deprecated rules from rector.php before upgrading Rector
- Prefer letting docbook rot be cleaned opportunistically during code edits
- Gate a dry-run in CI so tombstone registrations fail fast
When it happens
Trigger: Registering rules/DeadCode/Rector/ClassLike/RemoveTypedPropertyNonMockDocblockRector.php and running process/dry-run over any file containing a class. The throw fires at rules/DeadCode/Rector/ClassLike/RemoveTypedPropertyNonMockDocblockRector.php:52 on the first class visited — effectively the first file.
Common situations: Test-suite-focused configs (this rule targeted PHPUnit mock docblocks) still list it after upgrading rector/rector-prefixed. Because Class_ matches virtually every PHP file, the guard exception appears immediately and gets misreported as a broken Rector install.
Related errors
- "%s" rule is deprecated, as removing an annotation by name i
- "%s" rule is deprecated, as turning a docblock type into a r
- "%s" rule is deprecated, as too niche and of little practica
- "%s" rule is deprecated, as the param type guessed from a si
- "%s" is deprecated, as data provider docblock typing is not
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/5dcf6f34a3876cf8.
Report an issue: GitHub.