{"record":{"id":"84a4216e31088929","repo":"rectorphp/rector","slug":"file-object-is-missing-make-sure-you-call-this","errorCode":null,"errorMessage":"File object is missing. Make sure you call $this->currentFileProvider->setFile(...) before traversing.","messagePattern":"File object is missing\\. Make sure you call \\$this->currentFileProvider->setFile\\(\\.\\.\\.\\) before traversing\\.","errorType":"exception","errorClass":"ShouldNotHappenException","httpStatus":null,"severity":"error","filePath":"src/Rector/AbstractRector.php","lineNumber":164,"sourceCode":"            // notify this rule changed code\n            $rectorWithLineChange = new RectorWithLineChange(static::class, $originalNode->getStartLine());\n            $this->file->addRectorClassWithLine($rectorWithLineChange);\n            return $refactoredNodeOrState;\n        }\n        return $this->postRefactorProcess($originalNode, $node, $refactoredNodeOrState, $filePath);\n    }\n    /**\n     * @return mixed[]|int|\\PhpParser\\Node|null\n     */\n    final public function leaveNode(Node $node)\n    {\n        return null;\n    }\n    protected function getFile(): File\n    {\n        $file = $this->currentFileProvider->getFile();\n        if (!$file instanceof File) {\n            throw new ShouldNotHappenException('File object is missing. Make sure you call $this->currentFileProvider->setFile(...) before traversing.');\n        }\n        return $file;\n    }\n    protected function isName(Node $node, string $name): bool\n    {\n        return $this->nodeNameResolver->isName($node, $name);\n    }\n    /**\n     * @param string[] $names\n     */\n    protected function isNames(Node $node, array $names): bool\n    {\n        return $this->nodeNameResolver->isNames($node, $names);\n    }\n    /**\n     * Some nodes have always-known string name. This makes PHPStan smarter.\n     * @see https://phpstan.org/writing-php-code/phpdoc-types#conditional-return-types\n     *","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/rectorphp/rector/blob/408fcb0ff1833e3d26cbc9b04c23a77565814a16/src/Rector/AbstractRector.php#L146-L182","documentation":"AbstractRector::getFile() proxies CurrentFileProvider::getFile(). The provider is populated by the process pipeline (CurrentFileProvider->setFile(...) before each file is traversed). Calling getFile() outside that window — before traversal started or in a context that never set a file — yields null and throws ShouldNotHappenException telling you to call setFile() first.","triggerScenarios":"Unit tests that instantiate the rule and invoke refactor($node) directly; a rule calling $this->getFile() (or $this->file) from a constructor, configure(), or getRuleDefinition(); dry-run code paths that traverse cached/unchanged files without registering a File object.","commonSituations":"Fast unit tests bypassing AbstractRectorTestCase; rules that cache the file path eagerly at construction; a custom runner script that calls the traverser without the surrounding ProcessCommand lifecycle.","solutions":["Only call getFile() inside refactor()/node callbacks, i.e. during an actual traversal","For tests, use the standard AbstractRectorTestCase harness (it sets the provider), or set CurrentFileProvider->setFile(new File($path, $content)) before invoking the rule","Lazily resolve the file at use time instead of storing it in the constructor"],"exampleFix":"// before\nprotected function configure(): void\n{\n    $this->filePath = $this->getFile()->getFilePath(); // no file yet\n}\n\n// after: resolve lazily inside the node callback\npublic function refactor(Node $node): ?Node\n{\n    $filePath = $this->getFile()->getFilePath();\n    // ...\n}","handlingStrategy":"validation","validationCode":"// in tests driving a rule directly\n$file = new \\Rector\\FileSystem\\File(__DIR__ . '/Fixture.php', file_get_contents(__DIR__ . '/Fixture.php'));\n$currentFileProvider->setFile($file);\n\n$result = $rectorRule->refactor($node);","typeGuard":"function hasCurrentFile(\\Rector\\FileSystem\\CurrentFileProvider $provider): bool\n{\n    return $provider->getFile() instanceof \\Rector\\FileSystem\\File;\n}","tryCatchPattern":null,"preventionTips":["Call getFile() only inside refactor() or node callbacks during real traversal","Prefer AbstractRectorTestCase for rule tests — it wires CurrentFileProvider for you","Never resolve or store the file at construct time; do it lazily at use time"],"tags":["php","rector","custom-rule","lifecycle","current-file"],"backgroundTag":"missing-runtime-context","analyzedSha":"408fcb0ff1833e3d26cbc9b04c23a77565814a16","analyzedAt":"2026-08-21T05:11:02.643Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}