rectorphp/rector · error · ShouldNotHappenException
The installed package json not found. Make sure you run…
Error message
The installed package json not found. Make sure you run `composer update` and the "vendor/composer/installed.json" file exists
What it means
InstalledPackageResolver::resolve() reads <project>/vendor/composer/installed.json (honoring a custom config.vendor-dir) to learn installed package versions; those versions drive version-bonded sets (e.g. rules targeting the installed symfony/http-foundation version) and ComposerBasedCommand. If the file does not exist it throws ShouldNotHappenException, meaning the project's dependencies were never installed in the directory Rector is running against.
Solutions
- Run composer install (or composer update) in the project root so vendor/composer/installed.json exists
- Make sure you invoke rector from the directory that contains composer.json and vendor/ (check config.vendor-dir if customized)
- In CI, add the composer-install step before the rector step
- In monorepos, run rector per-package where the vendor lives, or point it at the package that owns the dependencies
Example fix
# before: CI runs rector on a fresh checkout - run: vendor/bin/rector process src # vendor/ not installed yet # after: install dependencies first - run: composer install --prefer-dist - run: vendor/bin/rector process src
Defensive patterns
Strategy: validation
Validate before calling
// preflight before invoking rector
$vendorDir = 'vendor'; // adjust if composer config.vendor-dir is custom
if (! is_file($vendorDir . '/composer/installed.json')) {
fwrite(STDERR, "Dependencies not installed; run `composer install` first\n");
exit(1);
} Try / catch
catch \Rector\Exception\ShouldNotHappenException in wrappers around rector; if the message mentions installed.json, run composer install and retry once.
Prevention
- Order CI steps: composer install always before rector
- Run rector from the directory that owns composer.json and vendor/
- Do not prune vendor/composer/* when slimming deployments if rector runs afterwards
When it happens
Trigger: Running rector in a project where composer install/update has not been run (no vendor/), where vendor/ was pruned, where config.vendor-dir points elsewhere than where dependencies were installed, or where the phar is executed from a directory that is not the project root (wrong cwd).
Common situations: CI step order running rector before composer install; deployments that ship code without vendor; running the rector phar from a parent/monorepo directory while composer.json lives in a sub-package.
Related errors
- a literal null byte in the regex
- an invalid bound
- an invalid character range
- an invalid escape sequence at the end
- an invalid or unsupported character class
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/117ecf6bf53ea4e0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Composer/InstalledPackageResolver.php:75
// the previous file is no longer the source, drop what was read from it
$this->resolvedInstalledPackages = null;
$this->projectComposerJson = null;
}
/**
* @return array<string, InstalledPackage>
*/
public function resolve(): array
{
// already cached, even only empty array
if ($this->resolvedInstalledPackages !== null) {
return $this->resolvedInstalledPackages;
}
if ($this->composerJsonFilePath !== null) {
return $this->resolvedInstalledPackages = $this->createPackagesFromConstraints();
}
$installedPackagesFilePath = $this->resolveVendorDir() . '/composer/installed.json';
if (!file_exists($installedPackagesFilePath)) {
throw new ShouldNotHappenException('The installed package json not found. Make sure you run `composer update` and the "vendor/composer/installed.json" file exists');
}
$installedPackageFileContents = FileSystem::read($installedPackagesFilePath);
$installedPackagesFilePath = Json::decode($installedPackageFileContents, \true);
$installedPackages = $this->createInstalledPackages($installedPackagesFilePath['packages']);
$this->resolvedInstalledPackages = $installedPackages;
return $installedPackages;
}
public function resolvePackageVersion(string $packageName): ?string
{
$package = $this->resolve()[$packageName] ?? null;
if (!$package instanceof InstalledPackage) {
return null;
}
return $package->getVersion();
}
/**
* @param mixed[] $packages
* @return array<string, InstalledPackage>View on GitHub (pinned to 408fcb0ff1)