symfony/routing · error · RuntimeException
Using "%% %%" is not allowed in routing configuration.
Error message
Using "%%%s%%" is not allowed in routing configuration.
What it means
Routing configuration is compiled and cached, so it must not contain raw %env(...)%% parameter placeholders (env vars are not available at route-compile time in production). The Router's parameter resolver rejects any %env(...)% placeholder found in routing values.
Solutions
- Remove the %env(...)% placeholder from the routing configuration.
- Move the env-dependent value into a container parameter (parameters.yaml binds env) and reference %parameter_name% instead.
- Use a route loader/condition or runtime requirement that evaluates env at request time rather than compile time.
- Keep the resolved parameter from itself containing an env placeholder chain to also avoid error [3].
Example fix
// before (routes.yaml) host: '%env(APP_HOST)%' // after # config/packages/app.yaml: parameters: app_host: '%env(APP_HOST)%' host: '%app_host%'
Defensive patterns
Strategy: validation
Validate before calling
if (preg_match('/%env\(/', $routeValue)) {
throw new LogicException('Route configuration must not contain %env(...)% placeholders.');
} Try / catch
try { $url = $generator->generate($name, $params); } catch (RuntimeException $e) { // env placeholder in routing config
throw new ConfigException('Fix routing config: '.$e->getMessage());
} Prevention
- Never use %env(...)% in routes.yaml/attributes
- Route env-dependent values through a container parameter
- Grep routing files for '%env(' in CI
When it happens
Trigger: A route definition (path, host, defaults, requirements) contains a placeholder like '%env(APP_SECRET)%' which Router::resolve matches while expanding %...% parameters.
Common situations: Copy-pasting container config syntax into routes.yaml; trying to read env vars in route hosts/defaults; framework.version upgrades surfacing legacy env placeholders in route files.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- The container parameter
- The container parameter
- Unable to generate a URL for the named route
- Target route " " for alias " " does not exist.
- Unable to generate a URL for the named route
AI-assisted analysis of symfony/routing@83fa223250 (2026-09-14).
Data as JSON: /api/errors/a66a0d908bd779a9.
Report an issue: GitHub.
Appendix: source
Thrown at DependencyInjection/Router.php:175
foreach ($value as $key => $val) {
$value[$key] = $this->resolve($val);
}
return $value;
}
if (!\is_string($value)) {
return $value;
}
$escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($value) {
// skip %%
if (!isset($match[1])) {
return '%%';
}
if (preg_match('/^env\((?:\w++:)*+\w++\)$/', $match[1])) {
throw new RuntimeException(\sprintf('Using "%%%s%%" is not allowed in routing configuration.', $match[1]));
}
$resolved = ($this->paramFetcher)($match[1]);
if (\is_string($resolved) && preg_match('/env_[a-f0-9]{16}_\w+_[a-f0-9]{32}/Ui', $resolved)) {
throw new RuntimeException(\sprintf('The container parameter "%s" resolves to an env var, which is not allowed in routing configuration.', $match[1]));
}
if (\is_scalar($resolved)) {
$this->collectedParameters[$match[1]] = $resolved;
if (\is_string($resolved)) {
$resolved = $this->resolve($resolved);
}
if (\is_scalar($resolved)) {
return false === $resolved ? '0' : (string) $resolved;
}View on GitHub (pinned to 83fa223250)