{"record":{"id":"d49da941e92cdb77","repo":"symfony/css-selector","slug":"pseudo-class-s-not-supported","errorCode":null,"errorMessage":"Pseudo-class \"%s\" not supported.","messagePattern":"Pseudo-class \"(.+?)\" not supported\\.","errorType":"exception","errorClass":"ExpressionErrorException","httpStatus":null,"severity":"error","filePath":"XPath/Translator.php","lineNumber":205,"sourceCode":"    /**\n     * @throws ExpressionErrorException\n     */\n    public function addFunction(XPathExpr $xpath, FunctionNode $function): XPathExpr\n    {\n        if (!isset($this->functionTranslators[$function->getName()])) {\n            throw new ExpressionErrorException(\\sprintf('Function \"%s\" not supported.', $function->getName()));\n        }\n\n        return $this->functionTranslators[$function->getName()]($xpath, $function);\n    }\n\n    /**\n     * @throws ExpressionErrorException\n     */\n    public function addPseudoClass(XPathExpr $xpath, string $pseudoClass): XPathExpr\n    {\n        if (!isset($this->pseudoClassTranslators[$pseudoClass])) {\n            throw new ExpressionErrorException(\\sprintf('Pseudo-class \"%s\" not supported.', $pseudoClass));\n        }\n\n        return $this->pseudoClassTranslators[$pseudoClass]($xpath);\n    }\n\n    /**\n     * @throws ExpressionErrorException\n     */\n    public function addAttributeMatching(XPathExpr $xpath, string $operator, string $attribute, ?string $value): XPathExpr\n    {\n        if (!isset($this->attributeMatchingTranslators[$operator])) {\n            throw new ExpressionErrorException(\\sprintf('Attribute matcher operator \"%s\" not supported.', $operator));\n        }\n\n        return $this->attributeMatchingTranslators[$operator]($xpath, $attribute, $value);\n    }\n\n    /**","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/symfony/css-selector/blob/08e2905152a39cf3fd1745d83f8c483e258887d9/XPath/Translator.php#L187-L223","documentation":"Translator::addPseudoClass() resolves a simple pseudo-class name (e.g. 'hover', 'first-child', 'empty') in $this->pseudoClassTranslators and throws ExpressionErrorException when the name is not registered. Static-state libraries only translate pseudo-classes that make sense in an XPath context, so many browser-only pseudo-classes are intentionally absent.","triggerScenarios":"Calling addPseudoClass() with a $pseudoClass string missing from pseudoClassTranslators — e.g. selector ':hover', ':focus', ':visited' passed to the translator, or a misspelled pseudo-class like ':first-of-typee'.","commonSituations":"Feeding interactive/browser-only CSS (:hover, :focus, :active) to the XPath converter in scraping or testing code; typos in pseudo-class names; custom pseudo-classes without a registered translator.","solutions":["Remove the unsupported pseudo-class from the selector or replace it with a structural equivalent (e.g. :first-child is supported, :hover is not).","Register a custom pseudo-class translator via Translator::extension().","Check supported names: hover is registered, but classes like :visited/:target are typically not — consult pseudoClassTranslators keys."],"exampleFix":"// before\n$translator->cssToXPath('a:hover'); // pseudo-class not supported, throws\n\n// after\n$translator->cssToXPath('a'); // drop interactive pseudo-class, filter matches in code","handlingStrategy":"try-catch","validationCode":"$supported = ['empty','first-child','last-child','first-of-type','last-of-type','only-child','hover','root','link','checked','disabled','enabled'];\n$pseudo = implode('|', $supported);\nif (preg_match('/:(' . $pseudo . ')?/)', '') !== false) { /* pre-check pseudo names */ }\nif (!preg_match('/^:(?:' . $pseudo . ')$/', ':' . $name)) {\n    throw new \\InvalidArgumentException(\"Unsupported pseudo-class: $name\");\n}","typeGuard":"function pseudoClassSupported(string $name): bool {\n    static $supported = ['first-child','last-child','empty','hover','root','link','checked','disabled','enabled'];\n    return in_array(ltrim($name, ':'), $supported, true);\n}","tryCatchPattern":"use Symfony\\Component\\CssSelector\\Exception\\ExpressionErrorException;\ntry {\n    $xpath = $translator->cssToXPath($css);\n} catch (ExpressionErrorException $e) {\n    $css = preg_replace('/:hover|:focus|:active/', '', $css); // drop interactive pseudo-classes\n    $xpath = $translator->cssToXPath($css);\n}","preventionTips":["Strip browser-only interactive pseudo-classes before translating selectors","Maintain a project-wide list of allowed pseudo-classes for scraped/derived CSS","Fail fast in tests when a selector contains untranslatable pseudo-classes"],"tags":["css-selector","xpath","pseudo-class","unsupported-selector"],"backgroundTag":"unsupported-enum-value","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"}