rectorphp/rector · error · ShouldNotHappenException
The installed package json not found. Make sure you run `com
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.
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)
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
- "%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
- "%s" is deprecated, as simplifying regex ranges is a persona
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/117ecf6bf53ea4e0.
Report an issue: GitHub.