rectorphp/rector · info

E_USER_DEPRECATED

E_USER_DEPRECATED

Error message

UseNodesToAddCollector::%s is deprecated and will be removed. Use "%s" instead, via $file->getFileNode().

What it means

An E_USER_DEPRECATED is triggered (UseNodesToAddCollector::warn(), src/PostRector/Collector/UseNodesToAddCollector.php:213) whenever custom Rector rule or extension code calls one of the collector's legacy import methods: addUseImport(), addConstantUseImport(), addFunctionUseImport(), getUseImportTypesByNode(), hasImport(), isShortImported(), isImportShortable(), getObjectImportsByFilePath(), getConstantImportsByFilePath() or getFunctionImportsByFilePath(). The import/import-manipulation state moved from this global collector onto the per-file FileNode / PendingImports object, reachable via $file->getFileNode(). The old methods still work (they delegate internally) but only emit this notice and will be removed.

Source

Thrown at src/PostRector/Collector/UseNodesToAddCollector.php:213

    {
        $this->warn('getFunctionImportsByFilePath()', '$file->getFileNode()->getPendingImports()->getFunctionImports()');
        $fileNode = $this->resolveCurrentFileNode();
        if (!$fileNode instanceof FileNode) {
            return [];
        }
        return $fileNode->getPendingImports()->getFunctionImports();
    }
    private function resolveCurrentFileNode(): ?FileNode
    {
        $file = $this->currentFileProvider->getFile();
        if (!$file instanceof File) {
            return null;
        }
        return $file->getFileNode();
    }
    private function warn(string $method, string $replacement): void
    {
        trigger_error(sprintf('UseNodesToAddCollector::%s is deprecated and will be removed. Use "%s" instead, via $file->getFileNode().', $method, $replacement), \E_USER_DEPRECATED);
    }
}

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Refactor the call site to the FileNode API named in the message: get the current file via CurrentFileProvider (or the rule's refected file) and call $file->getFileNode()->getPendingImports()->addUseImport($type) (or addConstantUseImport/addFunctionUseImport) for writes.
  2. For read-style calls use the direct replacements: hasImport($type) -> $fileNode->hasImport($type); getUseImportTypesByNode() -> $fileNode->resolveUsedImportTypes(); isShortImported()/isImportShortable()/get*ImportsByFilePath() -> the matching getPendingImports() methods on FileNode.
  3. If the call comes from a third-party rule, check for an upgraded release of that package; otherwise pin rector/rector to the version the rule was built for until it is ported.
  4. If you must keep CI green while migrating, temporarily silence E_USER_DEPRECATED (error_reporting(E_ALL & ~E_USER_DEPRECATED) or PHPUnit convertDeprecationsToExceptions="false") - but treat it as a stopgap, the methods will be removed.

Example fix

// before
use Rector\PostRector\Collector\UseNodesToAddCollector;

$this->useNodesToAddCollector->addUseImport($className); // triggers E_USER_DEPRECATED

// after
use Rector\PostRector\Collector\UseNodesToAddCollector;
use Rector\Application\FileProcessor; // not needed; use current file provider instead
$file = $this->currentFileProvider->getFile();
$file->getFileNode()->getPendingImports()->addUseImport($className);
Defensive patterns

Strategy: validation

Validate before calling

// detect deprecated collector calls before running Rector, e.g. as a CI grep/PHPStan gate
$deprecated = [
    'addUseImport', 'addConstantUseImport', 'addFunctionUseImport',
    'getUseImportTypesByNode', 'hasImport', 'isShortImported', 'isImportShortable',
    'getObjectImportsByFilePath', 'getConstantImportsByFilePath', 'getFunctionImportsByFilePath',
];
// quick gate over custom rules:
foreach (glob('src/*Rector.php') as $file) {
    $code = file_get_contents($file);
    foreach ($deprecated as $method) {
        if (str_contains($code, 'useNodesToAddCollector->' . $method)) {
            fwrite(STDERR, "{$file} uses deprecated UseNodesToAddCollector::{$method}()\n");
        }
    }
}

Try / catch

// only as a stopgap while migrating: keep deprecations from failing PHPUnit/CI
set_error_handler(function (int $errno, string $errstr): bool {
    if ($errno === E_USER_DEPRECATED && str_contains($errstr, 'UseNodesToAddCollector::')) {
        return true; // suppress; log $errstr if needed
    }
    return false; // default handler
});

Prevention

When it happens

Trigger: Writing a custom Rector rule that injects UseNodesToAddCollector and calls e.g. $this->useNodesToAddCollector->addUseImport($type) to queue a `use` import; calling hasImport()/isShortImported() in a rule's conditions; reading current imports via getObjectImportsByFilePath(); running third-party/custom rules built against an older rector/rector API during `vendor/bin/rector process` - each legacy call site logs one deprecation line (often surfaced by PHPUnit or an error_handler converting E_USER_DEPRECATED to exceptions).

Common situations: Maintaining private/company Rector rules that were written for Rector 1.x and running them under a newer version; CI setups with convertDeprecationsToExceptions="true" in phpunit.xml or a strict error handler that turns the notice into a failing test; copied rule code from old blog posts or the Rector playbook using the collector to add imports.

Related errors


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