symfony/routing · error · InvalidArgumentException

Namespace " " is not a valid PSR-4 prefix.

Error message

Namespace "%s" is not a valid PSR-4 prefix.

What it means

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.

Solutions

  1. 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).
  2. Ensure every segment matches [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* (letters, digits, underscore; must not start with a digit).
  3. Verify the config key used is 'namespace' and contains a namespace, not a filesystem path.

Example fix

// before
['path' => 'src', 'namespace' => 'app-controllers']
// after
['path' => 'src', 'namespace' => 'App\\Controllers']
Defensive patterns

Strategy: validation

Validate before calling

if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\)++$/', rtrim($ns, '\\') . '\\')) { throw new \InvalidArgumentException('Invalid PSR-4 prefix'); }

Try / catch

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; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of symfony/routing@83fa223250 (2026-09-14). Data as JSON: /api/errors/c1fda12a9ce73e33. Report an issue: GitHub.

Appendix: source

Thrown at Loader/Psr4DirectoryLoader.php:49

        private readonly FileLocatorInterface $locator,
    ) {
        // PSR-4 directory loader has no env-aware logic, so we drop the $env constructor parameter.
        parent::__construct();
    }

    /**
     * @param array{path: string, namespace: string} $resource
     */
    public function load(mixed $resource, ?string $type = null): ?RouteCollection
    {
        $excluded = $resource['_excluded'] ?? [];
        $path = $this->locator->locate($resource['path'], $this->currentDirectory);
        if (!is_dir($path)) {
            return new RouteCollection();
        }

        if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\)++$/', trim($resource['namespace'], '\\').'\\')) {
            throw new InvalidArgumentException(\sprintf('Namespace "%s" is not a valid PSR-4 prefix.', $resource['namespace']));
        }

        return $this->loadFromDirectory($path, trim($resource['namespace'], '\\'), $excluded);
    }

    public function supports(mixed $resource, ?string $type = null): bool
    {
        return 'attribute' === $type && \is_array($resource) && isset($resource['path'], $resource['namespace']);
    }

    public function forDirectory(string $currentDirectory): static
    {
        $loader = clone $this;
        $loader->currentDirectory = $currentDirectory;

        return $loader;
    }

View on GitHub (pinned to 83fa223250)