symfony/routing · error · LogicException

Cannot use UTF-8 route patterns without setting the "utf8"…

Error message

Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".

What it means

compilePattern detects that the route pattern (path or host) contains UTF-8 characters (high bytes \x80-\xFF) but the route's "utf8" option is not enabled. Since UTF-8 patterns require different regex matching, the compiler refuses to guess and throws a LogicException naming the route. This guard was introduced in Symfony 4.2/5.0 when UTF-8 route support became opt-in.

Solutions

  1. Set the utf8 option on the route: new Route('/café/{name}', options: ['utf8' => true]).
  2. In YAML, add options: { utf8: true } to the route definition.
  3. Alternatively, URL-encode or transliterate the pattern so it contains only ASCII characters.
  4. In Symfony 6.0+, UTF-8 is always enabled, so upgrade to remove the option requirement.

Example fix

// before
$route = new Route('/café/{name}');

// after
$route = new Route('/café/{name}', options: ['utf8' => true]);
Defensive patterns

Strategy: validation

Validate before calling

$path = $route->getPath();
$hasHighBytes = (bool) preg_match('/[\x80-\xFF]/', $path);
if ($hasHighBytes && !$route->getOption('utf8')) {
    $route->setOption('utf8', true); // or fail validation
}

Try / catch

try {
    $compiled = (new RouteCompiler())->compile($route);
} catch (\LogicException $e) {
    // enable utf8 or transliterate the pattern, then retry
}

Prevention

When it happens

Trigger: Compiling a route whose path or host contains non-ASCII characters (e.g. '/café/{name}') while the route's utf8 option is false/unset — e.g. new Route('/café/{name}') without ['utf8' => true].

Common situations: Localized/multilingual routes with accented or non-Latin characters; apps migrated from Symfony <4 where UTF-8 was implicit; routes loaded from config files saved in UTF-8 with special characters.

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/f85d0d14a2f912c7. Report an issue: GitHub.

Appendix: source

Thrown at RouteCompiler.php:118

            $hostRegex,
            $hostTokens,
            $hostVariables,
            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) {

View on GitHub (pinned to 83fa223250)