{"record":{"id":"21d058296ff98a04","repo":"symfony/routing","slug":"route-pattern-s-cannot-reference-variable-name-s-more-than","errorCode":null,"errorMessage":"Route pattern \"%s\" cannot reference variable name \"%s\" more than once.","messagePattern":"Route pattern \"(.+?)\" cannot reference variable name \"(.+?)\" more than once\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"RouteCompiler.php","lineNumber":150,"sourceCode":"            $pos = $match[0][1] + \\strlen($match[0][0]);\n\n            if (!\\strlen($precedingText)) {\n                $precedingChar = '';\n            } elseif ($useUtf8) {\n                preg_match('/.$/u', $precedingText, $precedingChar);\n                $precedingChar = $precedingChar[0];\n            } else {\n                $precedingChar = substr($precedingText, -1);\n            }\n            $isSeparator = '' !== $precedingChar && str_contains(static::SEPARATORS, $precedingChar);\n\n            // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the\n            // variable would not be usable as a Controller action argument.\n            if (preg_match('/^\\d/', $varName)) {\n                throw new \\DomainException(\\sprintf('Variable name \"%s\" cannot start with a digit in route pattern \"%s\". Please use a different name.', $varName, $pattern));\n            }\n            if (\\in_array($varName, $variables)) {\n                throw new \\LogicException(\\sprintf('Route pattern \"%s\" cannot reference variable name \"%s\" more than once.', $pattern, $varName));\n            }\n\n            if (\\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) {\n                throw new \\DomainException(\\sprintf('Variable name \"%s\" cannot be longer than %d characters in route pattern \"%s\". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern));\n            }\n\n            if ($isSeparator && $precedingText !== $precedingChar) {\n                $tokens[] = ['text', substr($precedingText, 0, -\\strlen($precedingChar))];\n            } elseif (!$isSeparator && '' !== $precedingText) {\n                $tokens[] = ['text', $precedingText];\n            }\n\n            $regexp = $route->getRequirement($varName);\n            if (null === $regexp) {\n                $followingPattern = substr($pattern, $pos);\n                // Find the next static character after the variable that functions as a separator. By default, this separator and '/'\n                // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all\n                // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/symfony/routing/blob/83fa223250b50f4f018c011e101c330e65ac63cc/RouteCompiler.php#L132-L168","documentation":"A route pattern may reference the same variable name only once; duplicates would produce an ambiguous PCRE named subpattern and the parameter value would be unclear. compilePattern keeps an accumulating $variables list (host variables first, then path variables) and throws a LogicException when a variable appears again.","triggerScenarios":"Compiling a route like /blog/{slug}/edit/{slug}, or a route whose host and path both contain the same variable, e.g. host '{subdomain}.example.com' with path '/{subdomain}/page'.","commonSituations":"Copy-pasting path segments and forgetting to rename the placeholder; templated route generation that appends the same parameter twice; combining host and path parameters with the same name.","solutions":["Rename one of the duplicated placeholders, e.g. /blog/{slug}/edit/{id}.","Remove the redundant placeholder if both segments carry the same data.","If host and path share a value, keep it in one place and use requirements/defaults for the other."],"exampleFix":"// before\n$route = new Route('/blog/{slug}/edit/{slug}');\n\n// after\n$route = new Route('/blog/{slug}/edit/{id}');","handlingStrategy":"validation","validationCode":"$vars = [];\npreg_match_all('/\\{(!)?([^}]+)\\}/', $route->getPath().' '.$route->getHost(), $m);\nforeach ($m[2] as $var) {\n    if (in_array($var, $vars, true)) {\n        throw new \\InvalidArgumentException(\"Variable '$var' is used more than once.\");\n    }\n    $vars[] = $var;\n}","typeGuard":null,"tryCatchPattern":"try {\n    (new RouteCompiler())->compile($route);\n} catch (\\LogicException $e) {\n    // deduplicate/rename placeholders before registering the route\n}","preventionTips":["Uniquely name every placeholder in a route (host and path share the same namespace).","Copy-paste route segments carefully; rename placeholders immediately after pasting.","Add a unit test that compiles all routes in RouteCollection during CI."],"tags":["routing","symfony","duplicate-variable","invalid-pattern"],"backgroundTag":"invalid-argument-format","analyzedSha":"83fa223250b50f4f018c011e101c330e65ac63cc","analyzedAt":"2026-09-14T03:19:46.280Z","contentChangedAt":"2026-09-14T03:19:46.280Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}