rectorphp/rector · error · InvalidConfigurationException
We could not find local "composer.json" to determine your PH
Error message
We could not find local "composer.json" to determine your PHP version.%sPlease, fill the PHP version set in withPhpSets() manually.
What it means
ComposerJsonPhpVersionResolver::resolveFromCwdOrFail() infers the project's PHP version by reading getcwd() . '/composer.json' and its require.php entry. Despite the message wording, it throws both when composer.json is absent from the cwd AND when it exists but yields no integer PHP requirement (e.g. no require.php key).
Source
Thrown at src/Php/PhpVersionResolver/ComposerJsonPhpVersionResolver.php:33
{
/**
* @var array<string, PhpVersion::*|null>
*/
private static array $cachedPhpVersions = [];
/**
* @return PhpVersion::*
*/
public static function resolveFromCwdOrFail(): int
{
// use composer.json PHP version
$projectComposerJsonFilePath = getcwd() . '/composer.json';
if (file_exists($projectComposerJsonFilePath)) {
$projectPhpVersion = self::resolve($projectComposerJsonFilePath);
if (is_int($projectPhpVersion)) {
return $projectPhpVersion;
}
}
throw new InvalidConfigurationException(sprintf('We could not find local "composer.json" to determine your PHP version.%sPlease, fill the PHP version set in withPhpSets() manually.', \PHP_EOL));
}
/**
* @return PhpVersion::*|null
*/
public static function resolve(string $composerJson): ?int
{
if (array_key_exists($composerJson, self::$cachedPhpVersions)) {
return self::$cachedPhpVersions[$composerJson];
}
$projectComposerJson = JsonFileSystem::readFilePath($composerJson);
// give this one a priority, as more generic one. see https://github.com/composer/composer/issues/7914
$requirePhpVersion = $projectComposerJson['require']['php'] ?? $projectComposerJson['require']['php-64bit'] ?? null;
if ($requirePhpVersion !== null) {
self::$cachedPhpVersions[$composerJson] = self::createIntVersionFromComposerVersion($requirePhpVersion);
return self::$cachedPhpVersions[$composerJson];
}
// see https://getcomposer.org/doc/06-config.md#platform
$platformPhp = $projectComposerJson['config']['platform']['php'] ?? null;View on GitHub (pinned to 408fcb0ff1)
Solutions
- Run rector from the directory that contains composer.json (usually the project root)
- Add a php constraint to require: "require": {"php": "^8.2"}
- Or stop relying on autodetection: pin the level explicitly with withPhpSets(php82: true) / withPhpLevel(PhpVersion::PHP_82)
Example fix
// before: rector.php relies on cwd detection return RectorConfig::configure()->withPhpSets(); // run from build/ -> throws // after: explicit level, cwd no longer matters use Rector\ValueObject\PhpVersion; return RectorConfig::configure()->withPhpLevel(PhpVersion::PHP_82);
Defensive patterns
Strategy: validation
Validate before calling
// before relying on autodetection
$composerJsonPath = getcwd() . '/composer.json';
if (! is_file($composerJsonPath)) {
throw new RuntimeException('Run Rector from the project root, or set an explicit PHP level.');
}
$require = json_decode((string) file_get_contents($composerJsonPath), true)['require'] ?? [];
if (! isset($require['php'])) {
throw new RuntimeException('composer.json has no require.php; set withPhpLevel() explicitly.');
} Prevention
- Invoke rector from the project root in composer scripts and CI (composer-run scripts inherit the right cwd)
- Pin the level explicitly in configs intended to run anywhere: withPhpLevel(PhpVersion::PHP_82)
- Keep a php constraint in require of every package Rector analyzes
When it happens
Trigger: Running vendor/bin/rector from a subdirectory or a directory without composer.json while rector.php calls withPhpSets() with no arguments; or a composer.json whose require section lacks a 'php'/'php-64bit' entry (e.g. only ext-* requirements).
Common situations: CI steps that cd into build/ or bin/ before invoking rector; monorepo tooling that executes from the workspace root while the config lives per-package; a library composer.json that never declared a php constraint.
Related errors
- Your config uses "withPhp*()" and "withPhpLevel()" methods a
- Pick only one version target in "withPhpSets()". All rules u
- Pick only one PHP version target in "withDowngradeSets()". A
- The "->withPhpSets()" method uses named arguments. Its suita
- Parameter "%s::%s" must be int, "%s" given.%sUse constant fr
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/40e752456cba4a3f.
Report an issue: GitHub.