rectorphp/rector · error · ShouldNotHappenException
Bootstrap file "%s" does not exist.
Error message
Bootstrap file "%s" does not exist.
What it means
BootstrapFilesIncluder loads every file listed in the BOOTSTRAP_FILES parameter (set by ->withBootstrapFiles([...]) in rector.php or --bootstrap-file on the CLI) before analysis starts, so user code needed by custom rules is loaded. Each path is checked with is_file() and a missing one aborts immediately with ShouldNotHappenException. Relative paths are resolved against the current working directory, which is the usual culprit.
Source
Thrown at src/Autoloading/BootstrapFilesIncluder.php:30
use SplFileInfo;
use RectorPrefix202608\Webmozart\Assert\Assert;
/**
* @see \Rector\Tests\Autoloading\BootstrapFilesIncluderTest
*/
final class BootstrapFilesIncluder
{
/**
* Inspired by
* @see https://github.com/phpstan/phpstan-src/commit/aad1bf888ab7b5808898ee5fe2228bb8bb4e4cf1
*/
public function includeBootstrapFiles(Container $container): void
{
$bootstrapFiles = SimpleParameterProvider::provideArrayParameter(Option::BOOTSTRAP_FILES);
Assert::allString($bootstrapFiles);
/** @var string[] $bootstrapFiles */
foreach ($bootstrapFiles as $bootstrapFile) {
if (!is_file($bootstrapFile)) {
throw new ShouldNotHappenException(sprintf('Bootstrap file "%s" does not exist.', $bootstrapFile));
}
// mimic PHPStan bootstrap file inclusion (bootstrap files have access to the global $container variable)
(static function (string $file) use ($container): void {
require $file;
})($bootstrapFile);
}
$this->requireRectorStubs();
}
private function requireRectorStubs(): void
{
$stubsRectorDirectory = realpath(__DIR__ . '/../../stubs-rector');
if ($stubsRectorDirectory === \false) {
return;
}
$dir = new RecursiveDirectoryIterator($stubsRectorDirectory, RecursiveDirectoryIterator::SKIP_DOTS);
$stubs = new RecursiveIteratorIterator($dir);
foreach ($stubs as $stub) {
/** @var SplFileInfo $stub */View on GitHub (pinned to 408fcb0ff1)
Solutions
- Use absolute paths anchored on the config file: ->withBootstrapFiles([__DIR__ . '/rector-bootstrap.php'])
- Verify the file exists: ls the exact path from the directory where you run rector
- If you run rector from another directory, cd to the project root or fix the relative path accordingly
Example fix
// before: relative path breaks when cwd differs
return RectorConfig::configure()
->withBootstrapFiles(['bootstrap/rector-bootstrap.php']);
// after: absolute path relative to the config file
return RectorConfig::configure()
->withBootstrapFiles([__DIR__ . '/bootstrap/rector-bootstrap.php']); Defensive patterns
Strategy: validation
Validate before calling
// in rector.php, before registering
$bootstrapFile = __DIR__ . '/bootstrap/rector-bootstrap.php';
if (! is_file($bootstrapFile)) {
throw new InvalidArgumentException('Bootstrap file missing: ' . $bootstrapFile);
}
return RectorConfig::configure()->withBootstrapFiles([$bootstrapFile]); Type guard
function isExistingBootstrapFile(string $path): bool
{
return is_file($path) && is_readable($path);
} Prevention
- Always build bootstrap paths with __DIR__ so they are cwd-independent
- Add bootstrap files to the same VCS/checkout as rector.php so CI always has them
- Use --bootstrap-file only with absolute paths in scripts
When it happens
Trigger: Calling ->withBootstrapFiles(['bootstrap/rector-bootstrap.php']) or --bootstrap-file=boot.php where the path is relative and rector runs from a different cwd (e.g. from a subdirectory, via a global binary, or in CI with a different working directory), or the file was simply deleted/renamed.
Common situations: Monorepo where rector runs at the repo root but rector.php lives in a package and uses relative paths; CI checking out the config without the bootstrap file; typos in the path.
Related errors
- "%s" rule is deprecated, as inverting nested ifs to early re
- "%s" rule is deprecated, as splitting a single condition int
- "%s" rule is deprecated, as splitting a single return into m
- "%s" is deprecated as risky change with little value. Use ma
- Provide only PHP file, ready for Dependency Injection. "%s"
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/813b46d6dc231e95.
Report an issue: GitHub.