{"record":{"id":"c1fda12a9ce73e33","repo":"symfony/routing","slug":"namespace-s-is-not-a-valid-psr-4-prefix","errorCode":null,"errorMessage":"Namespace \"%s\" is not a valid PSR-4 prefix.","messagePattern":"Namespace \"(.+?)\" is not a valid PSR-4 prefix\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"Loader/Psr4DirectoryLoader.php","lineNumber":49,"sourceCode":"        private readonly FileLocatorInterface $locator,\n    ) {\n        // PSR-4 directory loader has no env-aware logic, so we drop the $env constructor parameter.\n        parent::__construct();\n    }\n\n    /**\n     * @param array{path: string, namespace: string} $resource\n     */\n    public function load(mixed $resource, ?string $type = null): ?RouteCollection\n    {\n        $excluded = $resource['_excluded'] ?? [];\n        $path = $this->locator->locate($resource['path'], $this->currentDirectory);\n        if (!is_dir($path)) {\n            return new RouteCollection();\n        }\n\n        if (!preg_match('/^(?:[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+\\\\\\)++$/', trim($resource['namespace'], '\\\\').'\\\\')) {\n            throw new InvalidArgumentException(\\sprintf('Namespace \"%s\" is not a valid PSR-4 prefix.', $resource['namespace']));\n        }\n\n        return $this->loadFromDirectory($path, trim($resource['namespace'], '\\\\'), $excluded);\n    }\n\n    public function supports(mixed $resource, ?string $type = null): bool\n    {\n        return 'attribute' === $type && \\is_array($resource) && isset($resource['path'], $resource['namespace']);\n    }\n\n    public function forDirectory(string $currentDirectory): static\n    {\n        $loader = clone $this;\n        $loader->currentDirectory = $currentDirectory;\n\n        return $loader;\n    }\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/symfony/routing/blob/83fa223250b50f4f018c011e101c330e65ac63cc/Loader/Psr4DirectoryLoader.php#L31-L67","documentation":"Psr4DirectoryLoader validates that the 'namespace' key of its config array is a valid PSR-4 prefix: a non-empty sequence of namespace segments separated by backslashes. Anything else (missing trailing backslash context, empty segments, invalid characters, e.g. 'App', 'App\\', 'app\\helpers' with dashes) triggers this InvalidArgumentException.","triggerScenarios":"A Psr4Directory config like ['path' => 'src', 'namespace' => 'App\\Controllers'] that fails the regex, e.g. missing trailing backslash normalization, a leading digit, empty segment ('A\\\\B'), or trailing/leading stray backslashes in an odd position.","commonSituations":"Typo in the namespace config value; passing a directory-style path instead of a namespace; forgetting the trailing backslash in a hand-rolled config while trim only removes outer ones correctly but a segment is invalid; introducing dashes or dots from package conventions.","solutions":["Fix the namespace string to a valid PSR-4 prefix, e.g. 'App\\Controllers' (trim('\\\\') is applied, so the value itself should be like App\\\\Controllers).","Ensure every segment matches [a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]* (letters, digits, underscore; must not start with a digit).","Verify the config key used is 'namespace' and contains a namespace, not a filesystem path."],"exampleFix":"// before\n['path' => 'src', 'namespace' => 'app-controllers']\n// after\n['path' => 'src', 'namespace' => 'App\\\\Controllers']","handlingStrategy":"validation","validationCode":"if (!preg_match('/^(?:[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+\\\\)++$/', rtrim($ns, '\\\\') . '\\\\')) { throw new \\InvalidArgumentException('Invalid PSR-4 prefix'); }","typeGuard":null,"tryCatchPattern":"try { $collection = $loader->load($resource); } catch (\\InvalidArgumentException $e) { if (str_contains($e->getMessage(), 'PSR-4 prefix')) { throw new \\RuntimeException('Fix the namespace value in the route loader config', 0, $e); } throw $e; }","preventionTips":["Keep the namespace value a valid PSR-4 prefix like 'App\\\\Controller'.","Use backslash separators, never filesystem slashes or dashes/dots.","Validate each segment matches [A-Za-z_][A-Za-z0-9_]* and starts with a letter or underscore."],"tags":["symfony","routing","psr4","config"],"backgroundTag":"invalid-config-value","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"}