symfony/routing · error · InvalidArgumentException

The routing file " " must not specify both the "firewall"…

Error message

The routing file "%s" must not specify both the "firewall" key and the defaults key "_firewall" for "%s".

What it means

The firewall for a route may be set with the top-level 'firewall' key or via defaults['_firewall'], but specifying both is ambiguous and rejected. ContentLoaderTrait::validate() throws InvalidArgumentException when a route entry declares both.

Solutions

  1. Remove defaults['_firewall'] and keep only the top-level 'firewall' key
  2. Or delete the top-level 'firewall' key if the defaults form is required for your setup
  3. Audit routing files for both spellings after framework upgrades

Example fix

# before
app_secure:
    path: /secure
    firewall: main
    defaults:
        _firewall: main

# after
app_secure:
    path: /secure
    firewall: main
Defensive patterns

Strategy: validation

Validate before calling

if (isset($config['firewall']) && isset($config['defaults']['_firewall'])) {
    throw new \LogicException('Use either "firewall" or defaults._firewall, not both.');
}

Type guard

function hasSingleFirewall(array $config): bool { return !(isset($config['firewall']) && isset($config['defaults']['_firewall'])); }

Try / catch

try { $collection = $loader->load($file, 'yaml'); } catch (\InvalidArgumentException $e) { /* duplicate firewall declaration; dedupe config */ }

Prevention

When it happens

Trigger: A route entry in a routing file containing both 'firewall: ...' and 'defaults: { _firewall: ... }'.

Common situations: Configs maintained across Symfony versions where the option moved between defaults and top level; team members adding the newer key without deleting the legacy one; copy-paste from mixed documentation.

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


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

Appendix: source

Thrown at Loader/ContentLoaderTrait.php:235

            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));
            }

            if ('deprecated' === $key) {
                if (!isset($value['package'])) {

View on GitHub (pinned to 83fa223250)