rectorphp/rector · error · ShouldNotHappenException
Fixture file and input file cannot be the same:
Error message
Fixture file and input file cannot be the same:
What it means
AbstractRectorTestCase::doTestFile() splits a fixture into input/expected halves and writes the input half to a derived temp path (createInputFilePath()). Before FileSystem::write(), it verifies the derived path differs from the fixture path; equality would mean the write destroys the source fixture, so it throws ShouldNotHappenException with the colliding path.
Source
Thrown at src/Testing/PHPUnit/AbstractRectorTestCase.php:146
return null;
}
protected function doTestFile(string $fixtureFilePath, bool $includeFixtureDirectoryAsSource = \false): void
{
// prepare input file contents and expected file output contents
$fixtureFileContents = FileSystem::read($fixtureFilePath);
if (FixtureSplitter::containsSplit($fixtureFileContents)) {
// changed content
[$inputFileContents, $expectedFileContents] = FixtureSplitter::splitFixtureFileContents($fixtureFileContents);
} else {
// no change
$inputFileContents = $fixtureFileContents;
$expectedFileContents = $fixtureFileContents;
}
$inputFilePath = $this->createInputFilePath($fixtureFilePath);
// to remove later in tearDown()
$this->inputFilePath = $inputFilePath;
if ($fixtureFilePath === $inputFilePath) {
throw new ShouldNotHappenException('Fixture file and input file cannot be the same: ' . $fixtureFilePath);
}
// write temp file
FileSystem::write($inputFilePath, $inputFileContents, null);
$this->doTestFileMatchesExpectedContent($inputFilePath, $inputFileContents, $expectedFileContents, $fixtureFilePath, $includeFixtureDirectoryAsSource);
}
protected function doTestFileExpectingWarningAboutRuleApplied(string $fixtureFilePath, string $expectedRuleApplied): void
{
ob_start();
$this->doTestFile($fixtureFilePath);
$content = ob_get_clean();
$fixtureName = basename($fixtureFilePath);
$testClass = static::class;
$this->assertSame(\PHP_EOL . 'WARNING: On fixture file "' . $fixtureName . '" for test "' . $testClass . '"' . \PHP_EOL . 'File not changed but some Rector rules applied:' . \PHP_EOL . ' * ' . $expectedRuleApplied . \PHP_EOL, $content);
}
private function forgetRectorsRules(): void
{
$rectorConfig = self::getContainer();
// 1. forget tagged servicesView on GitHub (pinned to 408fcb0ff1)
Solutions
- Keep fixtures outside the temp/input directory (standard tests/Fixtures/ layout) so paths can never collide
- If you override createInputFilePath(), ensure it appends a distinct suffix (e.g. '.input' or '/input/') that the fixture itself does not carry
- Clear stale temp files between runs and re-run the test
Example fix
// before: fixture and derived input path coincide
protected function createInputFilePath(string $fixtureFilePath): string
{
return $fixtureFilePath; // identical -> throws
}
// after
protected function createInputFilePath(string $fixtureFilePath): string
{
return $fixtureFilePath . '.input';
} Defensive patterns
Strategy: validation
Validate before calling
// guard before doTestFile()
$inputFilePath = $this->createInputFilePath($fixtureFilePath);
if ($inputFilePath === $fixtureFilePath) {
self::markTestSkipped(sprintf('Fixture %s collides with its derived input path; move it out of the temp dir.', $fixtureFilePath));
} Prevention
- Store fixtures under a stable tests/Fixtures directory, never under sys_get_temp_dir()
- Keep createInputFilePath() derivations one-directional (fixture path + fixed suffix)
- Clean derived temp inputs in tearDown() so repeat runs start from a known state
When it happens
Trigger: The fixture already sits where the derived input path points — typically fixtures stored inside the temp directory that createInputFilePath() also uses, or a fixture filename whose transform (suffixing/extension swap) maps onto itself.
Common situations: Test suites relocated into sys_get_temp_dir() for CI isolation; a custom test case overriding createInputFilePath() without changing the suffix; running tests twice with cached temp fixtures from a prior aborted run.
Related errors
- Property "$%s" was not found in "%s" class
- "%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
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/93e8f445a903eb98.
Report an issue: GitHub.