rectorphp/rector · error · ParallelShouldNotHappenException

[parallel] Main script was not found

Error message

[parallel] Main script was not found

What it means

Rector runs files in parallel by re-invoking its own binary as child processes, so it must know which script started the run. resolveCalledRectorBinary() reads $_SERVER['argv'][0] and requires that value to be an existing file on disk; if argv[0] is unset or the file no longer exists, runParallel() aborts with ParallelShouldNotHappenException. This is an environment/invocation problem, not a problem with your code or config.

Source

Thrown at src/Application/ApplicationFileProcessor.php:245

            $this->systemErrors[] = new SystemError($message, $file, $line);
            return \true;
        };
        set_error_handler($errorHandlerCallback);
    }
    private function restoreErrorHandler(): void
    {
        restore_error_handler();
    }
    /**
     * @param string[] $filePaths
     * @param callable(int $stepCount): void $postFileCallback
     */
    private function runParallel(array $filePaths, InputInterface $input, callable $postFileCallback): ProcessResult
    {
        $schedule = $this->scheduleFactory->create($this->cpuCoreCountProvider->provide(), SimpleParameterProvider::provideIntParameter(Option::PARALLEL_JOB_SIZE), SimpleParameterProvider::provideIntParameter(Option::PARALLEL_MAX_NUMBER_OF_PROCESSES), $filePaths);
        $mainScript = $this->resolveCalledRectorBinary();
        if ($mainScript === null) {
            throw new ParallelShouldNotHappenException('[parallel] Main script was not found');
        }
        // mimics see https://github.com/phpstan/phpstan-src/commit/9124c66dcc55a222e21b1717ba5f60771f7dda92#diff-387b8f04e0db7a06678eb52ce0c0d0aff73e0d7d8fc5df834d0a5fbec198e5daR139
        return $this->parallelFileProcessor->process($schedule, $mainScript, $postFileCallback, $input);
    }
    /**
     * Path to called "rector" binary file, e.g. "vendor/bin/rector" returns "vendor/bin/rector" This is needed to re-call the
     * rector binary in sub-process in the same location.
     */
    private function resolveCalledRectorBinary(): ?string
    {
        if (!isset($_SERVER[self::ARGV][0])) {
            return null;
        }
        $potentialRectorBinaryPath = $_SERVER[self::ARGV][0];
        if (!file_exists($potentialRectorBinaryPath)) {
            return null;
        }
        return $potentialRectorBinaryPath;

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Run Rector directly through its CLI entry point: vendor/bin/rector process src (or rector.phar process src)
  2. If you wrap Rector, make sure $_SERVER['argv'][0] is set to the real, existing binary path before booting the console application
  3. Reinstall the binary so the file argv[0] points at exists: composer reinstall rector/rector or composer global update
  4. Avoid launching rector from php -r or an in-process include; shell out to the binary instead

Example fix

// before: custom runner that lost argv[0]
$_SERVER['argv'] = ['rector'];
$application->run();

// after: point argv[0] at the real binary file
$_SERVER['argv'][0] = __DIR__ . '/vendor/bin/rector';
$application->run();
Defensive patterns

Strategy: validation

Validate before calling

// before invoking rector programmatically, ensure argv[0] is a real binary file
$rectorBinary = __DIR__ . '/vendor/bin/rector';
if (!is_file($rectorBinary)) {
    throw new RuntimeException('rector binary missing at ' . $rectorBinary);
}
$_SERVER['argv'][0] = $rectorBinary; // child processes re-call this path

Try / catch

catch \Symplify\EasyParallel\Exception\ParallelShouldNotHappenException around the run and surface a hint: 'run rector directly via vendor/bin/rector so parallel workers can re-spawn the binary'. Do not retry blindly; fix the invocation.

Prevention

When it happens

Trigger: Running Rector with more files than fit one job when argv[0] is not a path to an existing file: invoking Rector programmatically from another PHP process, via php -r, through a custom wrapper/harness, or when the binary/symlink that started the process is deleted or moved mid-run (e.g. global symlink to an uninstalled vendor).

Common situations: CI pipelines that call rector through a bespoke runner script, global installations whose symlink target was removed by a composer update, or embedding rector in another tool that shims argv.

Related errors


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