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

  1. Remove RemoveTypedPropertyNonMockDocblockRector::class from rector.php and all imported set files, then re-run vendor/bin/rector dry-run
  2. Leave redundant @var docblocks alone, or delete them opportunistically while editing each file
  3. If you want them gone now, run a scoped one-off script or IDE cleanup on the tests directory
  4. 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

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


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