{"record":{"id":"9c841730de7dce5a","repo":"symfony/routing","slug":"the-file-s-does-not-contain-php-code-did-you-forget-to-add","errorCode":null,"errorMessage":"The file \"%s\" does not contain PHP code. Did you forget to add the \"<?php\" start tag at the beginning of the file?","messagePattern":"The file \"(.+?)\" does not contain PHP code\\. Did you forget to add the \"<\\?php\" start tag at the beginning of the file\\?","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"Loader/AttributeFileLoader.php","lineNumber":79,"sourceCode":"        return $collection;\n    }\n\n    public function supports(mixed $resource, ?string $type = null): bool\n    {\n        return \\is_string($resource) && 'php' === pathinfo($resource, \\PATHINFO_EXTENSION) && (!$type || 'attribute' === $type);\n    }\n\n    /**\n     * Returns the full class name for the first class in the file.\n     */\n    protected function findClass(string $file): string|false\n    {\n        $class = false;\n        $namespace = false;\n        $tokens = token_get_all(file_get_contents($file));\n\n        if (1 === \\count($tokens) && \\T_INLINE_HTML === $tokens[0][0]) {\n            throw new \\InvalidArgumentException(\\sprintf('The file \"%s\" does not contain PHP code. Did you forget to add the \"<?php\" start tag at the beginning of the file?', $file));\n        }\n\n        $nsTokens = [\\T_NS_SEPARATOR => true, \\T_STRING => true, \\T_NAME_QUALIFIED => true];\n        for ($i = 0; isset($tokens[$i]); ++$i) {\n            $token = $tokens[$i];\n            if (!isset($token[1])) {\n                continue;\n            }\n\n            if ($class && \\T_STRING === $token[0]) {\n                return $namespace.'\\\\'.$token[1];\n            }\n\n            if (true === $namespace && isset($nsTokens[$token[0]])) {\n                $namespace = $token[1];\n                while (isset($tokens[++$i][1], $nsTokens[$tokens[$i][0]])) {\n                    $namespace .= $tokens[$i][1];\n                }","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/symfony/routing/blob/83fa223250b50f4f018c011e101c330e65ac63cc/Loader/AttributeFileLoader.php#L61-L97","documentation":"findClass tokenizes the routing file and, if the entire file is a single T_INLINE_HTML token, no PHP was found — typically the file lacks the '<?php' opening tag. It throws InvalidArgumentException pointing at the file.","triggerScenarios":"A route class file saved without an opening <?php tag (or starting with a BOM/HTML before it), passed to the attribute route loader.","commonSituations":"Files created by editors/templates that emit plain text; heredoc-generated config files; renaming a template file to .php; files starting with a byte-order mark.","solutions":["Add '<?php' as the very first characters of the file (no leading HTML or BOM)","Verify the file actually contains the route class, not HTML/markdown","Check the file path passed to the loader points at a PHP class file"],"exampleFix":"// before (file content)\n<html><body>oops</body></html>\n// after\n<?php\nnamespace App\\Controller;\nuse Symfony\\Component\\Routing\\Annotation\\Route;\n#[Route('/blog')]\nclass BlogController {}","handlingStrategy":"validation","validationCode":"$head = substr((string) file_get_contents($file, false, null, 0, 20), ltrim($head, \"\\xEF\\xBB\\xBF\") ); if (!str_starts_with(ltrim($head), '<?php')) { throw new \\InvalidArgumentException(\"$file lacks <?php opening tag\"); }","typeGuard":"function isPhpSource(string $file): bool { return str_starts_with(ltrim(substr(file_get_contents($file, false, null, 0, 64), \"\\xEF\\xBB\\xBF\")), '<?php'); }","tryCatchPattern":"try { $routes = $loader->load($file); } catch (\\InvalidArgumentException $e) { if (str_contains($e->getMessage(), 'does not contain PHP code')) { /* check opening tag */ } throw $e; }","preventionTips":["Configure editors to insert <?php automatically in new PHP files","Strip BOMs in the build pipeline","Lint route files with php -l before loading"],"tags":["php","file-content","routing"],"backgroundTag":"invalid-argument-format","analyzedSha":"83fa223250b50f4f018c011e101c330e65ac63cc","analyzedAt":"2026-09-14T03:19:46.280Z","contentChangedAt":"2026-09-14T03:19:46.280Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}