rectorphp/rector · error · InvalidConfigurationException
Pick only one version target in "withPhpSets()". All rules u
Error message
Pick only one version target in "withPhpSets()". All rules up to this version will be used.%sTo use your composer.json PHP version, keep arguments empty.
What it means
withPhpSets() accepts one boolean per PHP version (php53..php86); passing more than one true flag is contradictory because the method means 'everything up to this version'. RectorConfigBuilder collects the true flags via array_filter and throws InvalidConfigurationException when count > 1. To target the composer.json version, pass no flags at all.
Source
Thrown at src/Configuration/RectorConfigBuilder.php:417
bool $php55 = \false,
bool $php54 = \false,
bool $php53 = \false,
// place on later as BC break when used in php 7.x without named arg
bool $php84 = \false,
bool $php85 = \false,
bool $php86 = \false
): self
{
if ($this->isWithPhpSetsUsed === \true) {
throw new InvalidConfigurationException(sprintf('Method "%s()" can be called only once. It always includes all previous sets UP TO the defined version.%sThe best practise is to call it once with no argument. That way it will pick up PHP version from composer.json and your project will always stay up to date.', __METHOD__, \PHP_EOL));
}
$this->isWithPhpSetsUsed = \true;
$pickedPhpVersions = array_keys(array_filter([PhpVersion::PHP_53 => $php53, PhpVersion::PHP_54 => $php54, PhpVersion::PHP_55 => $php55, PhpVersion::PHP_56 => $php56, PhpVersion::PHP_70 => $php70, PhpVersion::PHP_71 => $php71, PhpVersion::PHP_72 => $php72, PhpVersion::PHP_73 => $php73, PhpVersion::PHP_74 => $php74, PhpVersion::PHP_80 => $php80, PhpVersion::PHP_81 => $php81, PhpVersion::PHP_82 => $php82, PhpVersion::PHP_83 => $php83, PhpVersion::PHP_84 => $php84, PhpVersion::PHP_85 => $php85, PhpVersion::PHP_86 => $php86]));
if ($pickedPhpVersions !== []) {
Notifier::errorWithPhpSetsNotSuitableForPHP74AndLower();
}
if (count($pickedPhpVersions) > 1) {
throw new InvalidConfigurationException(sprintf('Pick only one version target in "withPhpSets()". All rules up to this version will be used.%sTo use your composer.json PHP version, keep arguments empty.', \PHP_EOL));
}
// no version picked, resolve it from the project composer.json
if ($pickedPhpVersions === []) {
return $this->addPhpLevelSets(ComposerJsonPhpVersionResolver::resolveFromCwdOrFail());
}
// explicitly picked version is a ceiling, even for polyfilled rules
$this->pickedPhpSetsVersion = $pickedPhpVersions[0];
return $this->addPhpLevelSets($pickedPhpVersions[0]);
}
public function withPhp53Sets(): self
{
return $this->reportDeprecatedPhpSetsMethod(__FUNCTION__);
}
public function withPhp54Sets(): self
{
return $this->reportDeprecatedPhpSetsMethod(__FUNCTION__);
}
public function withPhp55Sets(): selfView on GitHub (pinned to 408fcb0ff1)
Solutions
- Keep only the highest target flag: ->withPhpSets(php83: true)
- Better: call ->withPhpSets() with no arguments and let composer.json's php requirement define the ceiling
- Note the flags are cumulative by design -- you never need two to chain versions
Example fix
// before
return RectorConfig::configure()
->withPhpSets(php82: true, php83: true);
// after
return RectorConfig::configure()
->withPhpSets(php83: true); // includes everything up to 8.3 Defensive patterns
Strategy: validation
Validate before calling
// lint: exactly zero or one version flag in withPhpSets
if (preg_match('/withPhpSets\(([^)]*)\)/', $configSrc, $m)
&& preg_match_all('/php\d+:\s*true|(?<!:)\btrue\b/', $m[1], $flags) > 1
) {
fwrite(STDERR, "withPhpSets() got multiple version flags; keep only the highest\n");
} Try / catch
catch \Rector\Exception\Configuration\InvalidConfigurationException; on the 'Pick only one version target' message, keep the single highest flag and re-run.
Prevention
- Flags are cumulative: one call with the target version includes all lower sets
- Default to the argument-less form so composer.json drives the ceiling
- When bumping PHP versions, replace the old flag rather than appending
When it happens
Trigger: Calling ->withPhpSets(php82: true, php83: true), or adding a new version flag while forgetting to remove the old one; also older snippets using positional booleans (php74: true) combined with newer flags.
Common situations: Incremental upgrades where a developer adds the next version instead of replacing the previous flag; copy-pasted examples with different targets merged.
Related errors
- Your config uses "withPhp*()" and "withPhpLevel()" methods a
- Pick only one PHP version target in "withDowngradeSets()". A
- The "->withPhpSets()" method uses named arguments. Its suita
- "%s" rule is deprecated, as inverting nested ifs to early re
- "%s" rule is deprecated, as splitting a single condition int
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/8a568d2dc5b45ba9.
Report an issue: GitHub.