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
- Give each requirement its placeholder key: requirements: { id: '\d+' }.
- In YAML, use `requirements:` with `id: '\d+'` (map) rather than a dash-list.
- 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
- Always write requirements as maps: { placeholder: regex }.
- Avoid array_values/array_push on requirement maps.
- Lint YAML for dash-lists under 'requirements:'.
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
- The definition of " " in " " must be an array.
- Parameter " " for route " " must match " " (" " given) to…
- Parameters for route
- Route aliases cannot be used on non-invokable class
- The " ()" method must not be called.
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)