symfony/routing · error · InvalidArgumentException

A placeholder name must be a string

Error message

A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?

What it means

In parseRoute(), requirements must be keyed by placeholder name (string). A numeric key means a requirement was written as a bare list item without its placeholder key, e.g. "requirements: ['\\d+']" instead of "requirements: [id: '\\d+']". The loader throws an InvalidArgumentException telling you which requirement and route to fix.

Solutions

  1. Give each requirement its placeholder key: requirements: { id: '\d+' }.
  2. In YAML, use `requirements:` with `id: '\d+'` (map) rather than a dash-list.
  3. If building config in PHP, preserve keys — avoid array_values()/array_merge of such maps.

Example fix

// before
['requirements' => ['\d+']]
// after
['requirements' => ['id' => '\d+']]
Defensive patterns

Strategy: validation

Validate before calling

foreach ($requirements as $k => $v) { if (\is_int($k)) { throw new \InvalidArgumentException("Requirement for placeholder missing (got {$v})"); } }

Try / catch

try { $loader->load($file); } catch (\InvalidArgumentException $e) { /* fix the named requirement to use placeholder keys */ }

Prevention

When it happens

Trigger: YAML/PHP config where requirements uses numeric keys: `requirements: - '\d+'` or `[0 => '\d+']` in PHP arrays built programmatically (e.g. array_values() destroying keys).

Common situations: Hand-written YAML lists instead of maps; PHP config generated with array_push/array_values that drops string keys; copy-paste from docs losing indentation turning a map into a sequence.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at Loader/ContentLoaderTrait.php:87

            $deprecation = $config['deprecated'] ?? null;
            if (null !== $deprecation) {
                $alias->setDeprecated(
                    $deprecation['package'],
                    $deprecation['version'],
                    $deprecation['message'] ?? ''
                );
            }

            return;
        }

        $defaults = $config['defaults'] ?? [];
        $requirements = $config['requirements'] ?? [];
        $options = $config['options'] ?? [];

        foreach ($requirements as $placeholder => $requirement) {
            if (\is_int($placeholder)) {
                throw new \InvalidArgumentException(\sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path));
            }
        }

        if (isset($config['controller'])) {
            $defaults['_controller'] = $config['controller'];
        }
        if (isset($config['locale'])) {
            $defaults['_locale'] = $config['locale'];
        }
        if (isset($config['format'])) {
            $defaults['_format'] = $config['format'];
        }
        if (isset($config['utf8'])) {
            $options['utf8'] = $config['utf8'];
        }
        if (isset($config['stateless'])) {
            $defaults['_stateless'] = $config['stateless'];
        }

View on GitHub (pinned to 83fa223250)