symfony/routing · error · InvalidArgumentException
The "type" key for the route definition
Error message
The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.
What it means
Symfony's routing loader rejects a 'type' key on a route entry that does not also define 'resource'. The 'type' key exists only to select a custom loader for imports; a plain route definition (with 'path') has no loader to select, so the key is meaningless and the validate() method of ContentLoaderTrait throws InvalidArgumentException to catch the config mistake early.
Solutions
- Remove the 'type' key from the route definition — plain routes do not need a loader type
- If a loader type is actually needed, change the entry to an import: keep 'type' and add a 'resource' key
- Remove 'path' and restore 'resource' if the entry was meant to import routes
Example fix
# before
app_blog:
path: /blog
type: attribute
# after
app_blog:
path: /blog
controller: App\Controller\BlogController::index Defensive patterns
Strategy: validation
Validate before calling
if (isset($config['type']) && !isset($config['resource'])) {
throw new \InvalidArgumentException(sprintf('Route "%s": "type" requires a "resource" key (import).', $name));
} Type guard
function isImportWithValidType(array $config): bool { return !isset($config['type']) || isset($config['resource']); } Try / catch
try { $collection = $loader->load($file, 'yaml'); } catch (\InvalidArgumentException $e) { /* fix routing config referenced in $e->getMessage() */ } Prevention
- Never put 'type' on plain route definitions
- Reserve 'type' for imports that need a custom loader
- Lint routing files in CI (e.g. debug:router or config validation)
When it happens
Trigger: Loading a YAML/XML/PHP routing file whose entry has 'type' (e.g. type: attribute) but no 'resource' key — i.e. a direct route definition carrying a loader type.
Common situations: Copy-pasting an import block and editing 'resource' into 'path' while leaving 'type' behind; upgrading from old configs where 'type: annotation' was tolerated; hand-written routes that mimicked import syntax.
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"…
- You must define a "path" for the route
- The routing file " " must not specify both the "controller"…
AI-assisted analysis of symfony/routing@83fa223250 (2026-09-14).
Data as JSON: /api/errors/953d2ffba26c9485.
Report an issue: GitHub.
Appendix: source
Thrown at Loader/ContentLoaderTrait.php:223
*/
private function validate(mixed $config, string $name, string $path): void
{
if (!\is_array($config)) {
throw new \InvalidArgumentException(\sprintf('The definition of "%s" in "%s" must be an array.', $name, $path));
}
if (isset($config['alias'])) {
$this->validateAlias($config, $name, $path);
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.
*View on GitHub (pinned to 83fa223250)