symfony/routing · error · LogicException
Cannot mix UTF-8 requirements with non-UTF-8 pattern
Error message
Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".
What it means
The reverse of error 72: the route's "utf8" option is set to true but the pattern itself is not valid UTF-8 (preg_match('//u', $pattern) fails). Mixing UTF-8 requirements with a non-UTF-8 pattern would produce inconsistent regexes, so compilePattern throws a LogicException.
Solutions
- Re-save the route definition file with UTF-8 encoding.
- Fix the pattern string so it is valid UTF-8 (check with mb_check_encoding($path, 'UTF-8')).
- Remove the utf8 => true option if the pattern is intentionally non-UTF-8 ASCII.
- Normalize input with mb_convert_encoding($path, 'UTF-8', 'ISO-8859-1') before creating the route.
Example fix
// before (pattern bytes are Latin-1)
$route = new Route("/caf\xE9/{name}", options: ['utf8' => true]);
// after (valid UTF-8)
$route = new Route('/café/{name}', options: ['utf8' => true]); Defensive patterns
Strategy: validation
Validate before calling
if ($route->getOption('utf8') && !mb_check_encoding($route->getPath(), 'UTF-8')) {
throw new \RuntimeException('Route path is not valid UTF-8 but the utf8 option is enabled.');
} Try / catch
try {
(new RouteCompiler())->compile($route);
} catch (\LogicException $e) {
// fix encoding (mb_convert_encoding) or drop the utf8 option, then retry
} Prevention
- Enforce UTF-8 file encoding (and BOM-free) for all routing config via CI checks.
- Validate external/user-supplied strings with mb_check_encoding before building routes.
- Normalize strings with mb_convert_encoding when importing route data.
When it happens
Trigger: Compiling a route with options ['utf8' => true] whose path or host pattern is invalid or non-UTF-8 encoded bytes (e.g. a Latin-1 encoded config file containing '/café').
Common situations: Config files saved with the wrong encoding (ISO-8859-1 instead of UTF-8); routes built from external data with broken encoding; enabling utf8 globally but having legacy ASCII-escaped patterns.
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 use UTF-8 route requirements without setting the…
- 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/d12b6cc0023d64c4.
Report an issue: GitHub.
Appendix: source
Thrown at RouteCompiler.php:121
array_unique($variables)
);
}
private static function compilePattern(Route $route, string $pattern, bool $isHost): array
{
$tokens = [];
$variables = [];
$matches = [];
$pos = 0;
$defaultSeparator = $isHost ? '.' : '/';
$useUtf8 = preg_match('//u', $pattern);
$needsUtf8 = $route->getOption('utf8');
if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) {
throw new \LogicException(\sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath()));
}
if (!$useUtf8 && $needsUtf8) {
throw new \LogicException(\sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern));
}
// Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable
// in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself.
preg_match_all('#\{(!)?([\w\x80-\xFF]+)\}#', $pattern, $matches, \PREG_OFFSET_CAPTURE | \PREG_SET_ORDER);
foreach ($matches as $match) {
$important = $match[1][1] >= 0;
$varName = $match[2][0];
// get all static text preceding the current variable
$precedingText = substr($pattern, $pos, $match[0][1] - $pos);
$pos = $match[0][1] + \strlen($match[0][0]);
if (!\strlen($precedingText)) {
$precedingChar = '';
} elseif ($useUtf8) {
preg_match('/.$/u', $precedingText, $precedingChar);
$precedingChar = $precedingChar[0];
} else {View on GitHub (pinned to 83fa223250)