symfony/routing · error · InvalidArgumentException

The return value in config file

Error message

The return value in config file "%s" is expected to be a RouteCollection, an array or a configurator callable, but got "%s".

What it means

PhpFileLoader expects a route config PHP file to return a RouteCollection, an array of route definitions, or an invokable configurator object. Any other return value triggers this InvalidArgumentException, telling you the actual type returned via get_debug_type().

Solutions

  1. Make the config file return one of: a RouteCollection, an array (with ->setDefault etc. or nested route arrays), or an invokable configurator.
  2. If returning null, add the missing return statement.
  3. Check with get_debug_type in the message what type was actually returned and correct it.

Example fix

// before
<?php // config/routes/x.php
$collection = new RouteCollection(); $collection->add(...);
// (no return -> null)
// after
<?php
$collection = new RouteCollection(); $collection->add(...);
return $collection;
Defensive patterns

Strategy: validation

Validate before calling

$result = require $path;
if (!$result instanceof RouteCollection && !is_array($result) && !(is_object($result) && is_callable($result))) {
  throw new \InvalidArgumentException(sprintf('%s must return RouteCollection|array|callable, got %s', $path, get_debug_type($result)));
}

Try / catch

try { $collection = $phpLoader->load($path); } catch (\InvalidArgumentException $e) { if (str_contains($e->getMessage(), 'expected to be a RouteCollection')) { throw new \RuntimeException("Bad route config file: $path", 0, $e); } throw $e; }

Prevention

When it happens

Trigger: A config/routes/*.php file whose return statement yields e.g. a string, null, true/false, or an unrelated object (non-callable), while loading routes through PhpFileLoader.

Common situations: Hand-writing route PHP files and forgetting the return statement (returns null); returning a builder object instead of the collection; migrating YAML routes and mixing in plain values.

Related errors


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

Appendix: source

Thrown at Loader/PhpFileLoader.php:64

        }

        // the closure forbids access to the private scope in the included file
        $loader = $this;
        $load = \Closure::bind(static function ($file) use ($loader) {
            return include $file;
        }, null, null);

        if (1 === $result = $load($path)) {
            $result = null;
        }

        if (\is_object($result) && \is_callable($result)) {
            $collection = $this->callConfigurator($result, $path, $file);
        } elseif (\is_array($result)) {
            $collection = new RouteCollection();
            $this->loadContent($collection, $result, $path, $file);
        } elseif (!($collection = $result) instanceof RouteCollection) {
            throw new InvalidArgumentException(\sprintf('The return value in config file "%s" is expected to be a RouteCollection, an array or a configurator callable, but got "%s".', $path, get_debug_type($result)));
        }

        $collection->addResource(new FileResource($path));

        return $collection;
    }

    public function supports(mixed $resource, ?string $type = null): bool
    {
        return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'php' === $type);
    }

    /**
     * @param-immediately-invoked-callable $callback
     */
    protected function callConfigurator(callable $callback, string $path, string $file): RouteCollection
    {
        $collection = new RouteCollection();

View on GitHub (pinned to 83fa223250)