{"record":{"id":"2723e399d3e917ba","repo":"symfony/css-selector","slug":"got-too-deeply-nested-s","errorCode":null,"errorMessage":"Got too deeply nested :%s().","messagePattern":"Got too deeply nested :(.+?)\\(\\)\\.","errorType":"exception","errorClass":"SyntaxErrorException","httpStatus":null,"severity":"error","filePath":"Parser/Parser.php","lineNumber":375,"sourceCode":"            }\n        }\n\n        if (\\count($stream->getUsed()) === $selectorStart) {\n            throw SyntaxErrorException::unexpectedToken('selector', $stream->getPeek());\n        }\n\n        return [$result, $pseudoElement];\n    }\n\n    /**\n     * @return Node\\SelectorNode[]\n     *\n     * @throws SyntaxErrorException\n     */\n    private function parseNestedSelectorList(TokenStream $stream, string $identifier): array\n    {\n        if ($this->nestingDepth >= self::NESTING_LIMIT) {\n            throw new SyntaxErrorException(\\sprintf('Got too deeply nested :%s().', $identifier));\n        }\n\n        ++$this->nestingDepth;\n\n        try {\n            return $this->parseSelectorList($stream, true);\n        } finally {\n            --$this->nestingDepth;\n        }\n    }\n\n    private function parseElementNode(TokenStream $stream): Node\\ElementNode\n    {\n        $peek = $stream->getPeek();\n\n        if ($peek->isIdentifier() || $peek->isDelimiter(['*'])) {\n            if ($peek->isIdentifier()) {\n                $namespace = $stream->getNext()->getValue();","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/symfony/css-selector/blob/08e2905152a39cf3fd1745d83f8c483e258887d9/Parser/Parser.php#L357-L393","documentation":"SyntaxErrorException thrown by Parser::parseNestedSelectorList when CSS nesting (e.g. :is(), :has(), :not() argument selectors) exceeds the parser's fixed NESTING_LIMIT. The library imposes this cap to prevent stack overflows / denial-of-service on deeply nested malicious selectors. It is a hard compile-time limit, not a tunable option.","triggerScenarios":"Calling Translator::cssToXPath (or the Parser directly) with a selector whose nested functional pseudo-classes are nested more than self::NESTING_LIMIT levels deep, e.g. :is(:is(:is(...))) repeated past the limit.","commonSituations":"Programmatically generated selectors (loops building nested :not/:is chains), user-supplied CSS selectors processed server-side, minified or concatenated selector strings from bundlers.","solutions":["Flatten or reduce the nesting depth of the selector (merge redundant :is()/:not() wrappers).","Catch Symfony\\Component\\CssSelector\\Exception\\SyntaxErrorException around cssToXPath and reject the input as invalid CSS.","Pre-check user-supplied selector strings for nesting depth before parsing.","If a deeper limit is genuinely needed, fork/patch the NESTING_LIMIT constant in Parser (no runtime config exists)."],"exampleFix":"// before\n$xpath = $translator->cssToXPath($userSelector); // throws on deep nesting\n// after\ntry {\n    $xpath = $translator->cssToXPath($userSelector);\n} catch (SyntaxErrorException $e) {\n    $xpath = null; // reject selector\n}","handlingStrategy":"try-catch","validationCode":"function isSafeSelectorDepth(string $css, int $max = 15): bool {\n    $depth = 0; $maxSeen = 0;\n    foreach (str_split($css) as $c) {\n        if ($c === '(') { $maxSeen = max($maxSeen, ++$depth); }\n        elseif ($c === ')') { --$depth; }\n    }\n    return $maxSeen <= $max;\n}","typeGuard":"function hasAcceptableNesting(string $css): bool { return substr_count($css, ':') <= 20 && substr_count($css, '(') <= 15; }","tryCatchPattern":"try {\n    $xpath = $translator->cssToXPath($css);\n} catch (\\Symfony\\Component\\CssSelector\\Exception\\SyntaxErrorException $e) {\n    if (str_contains($e->getMessage(), 'too deeply nested')) {\n        // reject selector\n    }\n}","preventionTips":["Cap user-supplied selector length and parenthesis depth before parsing.","Do not build :is()/:not() chains in loops.","Run cssToXPath inside try-catch whenever input is not fully controlled.","Pin selector generation templates to known-flat shapes."],"tags":["css-selector","parser","recursion-limit"],"backgroundTag":"value-out-of-range","analyzedSha":"08e2905152a39cf3fd1745d83f8c483e258887d9","analyzedAt":"2026-09-14T11:41:28.509Z","contentChangedAt":"2026-09-14T11:41:28.509Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}