symfony/routing · error · InvalidArgumentException
The routing file " " must not specify both the "stateless"…
Error message
The routing file "%s" must not specify both the "stateless" key and the defaults key "_stateless" for "%s".
What it means
Statelessness can be declared with the route-level 'stateless' key or via defaults['_stateless'], never both. ContentLoaderTrait::validate() throws InvalidArgumentException when both appear, since the two settings could disagree and Symfony refuses to guess.
Solutions
- Keep the top-level 'stateless' key and remove defaults['_stateless']
- Or remove the top-level 'stateless' key if you intentionally rely on the defaults form (older style)
- Grep routing files for '_stateless' after version upgrades
Example fix
# before
app_api:
path: /api
stateless: true
defaults:
_stateless: true
# after
app_api:
path: /api
stateless: true Defensive patterns
Strategy: validation
Validate before calling
if (isset($config['stateless']) && isset($config['defaults']['_stateless'])) {
throw new \LogicException('Use either "stateless" or defaults._stateless, not both.');
} Type guard
function hasSingleStateless(array $config): bool { return !(isset($config['stateless']) && isset($config['defaults']['_stateless'])); } Try / catch
try { $collection = $loader->load($file, 'yaml'); } catch (\InvalidArgumentException $e) { /* duplicate stateless declaration; dedupe config */ } Prevention
- Use only the top-level 'stateless' key on modern Symfony
- Remove legacy defaults._stateless after upgrades
- Add a config lint step to CI
When it happens
Trigger: A route entry containing both 'stateless: true' (top-level) and 'defaults: { _stateless: true }' in the same routing file.
Common situations: Upgrading configs from Symfony versions where _stateless in defaults was the documented form; mixing snippets from docs of different versions; merge conflicts resolved by keeping both lines.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- The definition of " " in " " must be an array.
- The routing file " " contains unsupported keys for " ": "…
- The routing file " " must not specify both the "resource"…
- The "type" key for the route definition
- You must define a "path" for the route
AI-assisted analysis of symfony/routing@83fa223250 (2026-09-14).
Data as JSON: /api/errors/6db2fdbe7a42f96d.
Report an issue: GitHub.
Appendix: source
Thrown at Loader/ContentLoaderTrait.php:232
return;
}
if ($extraKeys = array_diff(array_keys($config), self::AVAILABLE_KEYS)) {
throw new \InvalidArgumentException(\sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::AVAILABLE_KEYS)));
}
if (isset($config['resource']) && isset($config['path'])) {
throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name));
}
if (!isset($config['resource']) && isset($config['type'])) {
throw new \InvalidArgumentException(\sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path));
}
if (!isset($config['resource']) && !isset($config['path'])) {
throw new \InvalidArgumentException(\sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path));
}
if (isset($config['controller']) && isset($config['defaults']['_controller'])) {
throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name));
}
if (isset($config['stateless']) && isset($config['defaults']['_stateless'])) {
throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "stateless" key and the defaults key "_stateless" for "%s".', $path, $name));
}
if (isset($config['firewall']) && isset($config['defaults']['_firewall'])) {
throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify both the "firewall" key and the defaults key "_firewall" for "%s".', $path, $name));
}
}
/**
* Validates that an alias definition only carries the `alias` and `deprecated` keys.
*
* @throws \InvalidArgumentException If one of the provided config keys is not supported,
* something is missing or the combination is nonsense
*/
private function validateAlias(array $config, string $name, string $path): void
{
foreach ($config as $key => $value) {
if (!\in_array($key, ['alias', 'deprecated'], true)) {
throw new \InvalidArgumentException(\sprintf('The routing file "%s" must not specify other keys than "alias" and "deprecated" for "%s".', $path, $name));
}View on GitHub (pinned to 83fa223250)