symfony/routing · error · LogicException
Cannot use UTF-8 route requirements without setting the…
Error message
Cannot use UTF-8 route requirements without setting the "utf8" option for variable "%s" in pattern "%s".
What it means
A route variable's requirement regex uses UTF-8 features (high bytes, \X, unicode \p{...} classes) while the route's "utf8" option is not enabled. The compiled regex would be applied byte-wise and misbehave, so compilePattern throws a LogicException asking you to enable utf8 for that variable's pattern.
Solutions
- Enable the utf8 option: new Route('/{city}', options: ['utf8' => true], requirements: ['city' => '[\p{L}]+']).
- In YAML, set options: { utf8: true } on the route.
- Rewrite the requirement to be ASCII-only, e.g. '[a-zA-Z]+' or '[^/]+', if UTF-8 matching is not needed.
- Upgrade to Symfony 6+, where UTF-8 mode is always on and the option no longer exists.
Example fix
// before
$route = new Route('/{city}', [], ['city' => '[\p{L}]+']);
// after
$route = new Route('/{city}', options: ['utf8' => true], requirements: ['city' => '[\p{L}]+']); Defensive patterns
Strategy: validation
Validate before calling
foreach ($route->getRequirements() as $name => $req) {
if (preg_match('/[\x80-\xFF]|\\\\(?:\\\\)*+(?-i:X|[pP][\{CLMNPSZ]|x\{[A-Fa-f0-9]{3})/', $req)
&& !$route->getOption('utf8')) {
$route->setOption('utf8', true); // or reject
}
} Try / catch
try {
(new RouteCompiler())->compile($route);
} catch (\LogicException $e) {
// enable utf8 or make requirements ASCII-only, then retry
} Prevention
- Whenever you use \p{...} or literal non-ASCII in requirements, set utf8: true.
- Prefer ASCII-only requirements ([a-zA-Z0-9-]+) in reusable bundles.
- Test-compile all routes in CI to catch option/requirement mismatches.
When it happens
Trigger: Compiling a route like new Route('/{city}', ['utf8' => false], ['city' => '[\p{L}]+']) or with a requirement containing literal accented characters, without the utf8 option.
Common situations: Adding unicode-aware requirements (\p{L}, \p{N}, accented character classes) to pre-UTF-8-era route definitions; copying requirements from a UTF-8-enabled project into a Symfony 4/5 project with utf8 unset.
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
- Cannot mix UTF-8 requirement with non-UTF-8 charset for…
- Cannot use UTF-8 route patterns without setting the "utf8"…
- Cannot mix UTF-8 requirements with non-UTF-8 pattern
- Parameter " " for route " " must match " " (" " given) to…
- Parameters for route
AI-assisted analysis of symfony/routing@83fa223250 (2026-09-14).
Data as JSON: /api/errors/b419eb303fcee5e3.
Report an issue: GitHub.
Appendix: source
Thrown at RouteCompiler.php:191
$nextSeparator = self::findNextSeparator($followingPattern, $useUtf8);
$regexp = \sprintf(
'[^%s%s]+',
preg_quote($defaultSeparator),
$defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator) : ''
);
if (('' !== $nextSeparator && !preg_match('#^\{[\w\x80-\xFF]+\}#', $followingPattern)) || '' === $followingPattern) {
// When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive
// quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns.
// Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow
// after it. This optimization cannot be applied when the next char is no real separator or when the next variable is
// directly adjacent, e.g. '/{x}{y}'.
$regexp .= '+';
}
} else {
if (!preg_match('//u', $regexp)) {
$useUtf8 = false;
} elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?<!\\\\)\\\\(?:\\\\\\\\)*+(?-i:X|[pP][\{CLMNPSZ]|x\{[A-Fa-f0-9]{3})/', $regexp)) {
throw new \LogicException(\sprintf('Cannot use UTF-8 route requirements without setting the "utf8" option for variable "%s" in pattern "%s".', $varName, $pattern));
}
if (!$useUtf8 && $needsUtf8) {
throw new \LogicException(\sprintf('Cannot mix UTF-8 requirement with non-UTF-8 charset for variable "%s" in pattern "%s".', $varName, $pattern));
}
$regexp = self::transformCapturingGroupsToNonCapturings($regexp);
}
if ($important) {
$token = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName, false, true];
} else {
$token = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName];
}
$tokens[] = $token;
$variables[] = $varName;
}
if ($pos < \strlen($pattern)) {View on GitHub (pinned to 83fa223250)