{"record":{"id":"56638764df803d66","repo":"symfony/routing","slug":"variable-name-s-cannot-start-with-a-digit-in-route-pattern-s","errorCode":null,"errorMessage":"Variable name \"%s\" cannot start with a digit in route pattern \"%s\". Please use a different name.","messagePattern":"Variable name \"(.+?)\" cannot start with a digit in route pattern \"(.+?)\"\\. Please use a different name\\.","errorType":"exception","errorClass":"DomainException","httpStatus":null,"severity":"error","filePath":"RouteCompiler.php","lineNumber":147,"sourceCode":"            $varName = $match[2][0];\n            // get all static text preceding the current variable\n            $precedingText = substr($pattern, $pos, $match[0][1] - $pos);\n            $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);","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/symfony/routing/blob/83fa223250b50f4f018c011e101c330e65ac63cc/RouteCompiler.php#L129-L165","documentation":"Route variable names extracted from {placeholders} must start with a non-digit: PCRE subpattern names and PHP variables cannot begin with a digit, so the value could never be used as a controller action argument. compilePattern throws a DomainException when the variable name matches /^\\d/.","triggerScenarios":"Compiling a route with a placeholder like /blog/{2fa_code}, /items/{0id}, or any {<digit>...} variable name.","commonSituations":"Placeholders meant to denote numbered items ({1st}, {2fa}); generated route names from data with numeric keys; typos where a digit replaced a letter.","solutions":["Rename the variable to start with a letter or underscore, e.g. {2fa_code} → {twoFactorCode} or {_2fa_code}.","Pass the numeric part as a fixed prefix or default instead of a variable, e.g. /blog/2fa/{code}.","Search route definitions with a regex like \\{\\d for offending placeholders."],"exampleFix":"// before\n$route = new Route('/login/{2fa_code}');\n\n// after\n$route = new Route('/login/{twoFactorCode}');","handlingStrategy":"validation","validationCode":"preg_match_all('/\\{(!)?([^}]+)\\}/', $route->getPath(), $m);\nforeach ($m[2] as $var) {\n    if (preg_match('/^\\d/', $var)) {\n        throw new \\InvalidArgumentException(\"Variable '$var' must not start with a digit.\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    (new RouteCompiler())->compile($route);\n} catch (\\DomainException $e) {\n    // rename the offending variable and recompile\n}","preventionTips":["Adopt a naming convention for placeholders (camelCase starting with a letter).","When generating routes from data, sanitize keys: preg_replace('/^\\d+/', '_', $key).","Spell out numbers in parameter names ({twoFactorCode}, not {2fa})."],"tags":["routing","symfony","variable-naming","invalid-identifier"],"backgroundTag":"invalid-identifier-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"}