{"record":{"id":"45132e37aadf4b14","repo":"symfony/css-selector","slug":"first-of-type-is-not-implemented","errorCode":null,"errorMessage":"\"*:first-of-type\" is not implemented.","messagePattern":"\"\\*:first-of-type\" is not implemented\\.","errorType":"exception","errorClass":"ExpressionErrorException","httpStatus":null,"severity":"error","filePath":"XPath/Extension/PseudoClassExtension.php","lineNumber":76,"sourceCode":"            ->addNameTest()\n            ->addCondition('position() = 1');\n    }\n\n    public function translateLastChild(XPathExpr $xpath): XPathExpr\n    {\n        return $xpath\n            ->addStarPrefix()\n            ->addNameTest()\n            ->addCondition('position() = last()');\n    }\n\n    /**\n     * @throws ExpressionErrorException\n     */\n    public function translateFirstOfType(XPathExpr $xpath): XPathExpr\n    {\n        if ('*' === $xpath->getElement()) {\n            throw new ExpressionErrorException('\"*:first-of-type\" is not implemented.');\n        }\n\n        return $xpath\n            ->addStarPrefix()\n            ->addCondition('position() = 1');\n    }\n\n    /**\n     * @throws ExpressionErrorException\n     */\n    public function translateLastOfType(XPathExpr $xpath): XPathExpr\n    {\n        if ('*' === $xpath->getElement()) {\n            throw new ExpressionErrorException('\"*:last-of-type\" is not implemented.');\n        }\n\n        return $xpath\n            ->addStarPrefix()","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/symfony/css-selector/blob/08e2905152a39cf3fd1745d83f8c483e258887d9/XPath/Extension/PseudoClassExtension.php#L58-L94","documentation":"ExpressionErrorException thrown by PseudoClassExtension::translateFirstOfType when the XPath element is the universal selector '*'. Determining 'first of its element type' requires knowing the type; with '*' the emitted XPath would be meaningless, so the library explicitly rejects '*:first-of-type'.","triggerScenarios":"Translating '*:first-of-type' directly, or compound selectors whose element part resolves to universal (e.g. '* > p:first-of-type' is fine, but bare '*:first-of-type' is not) via Translator::cssToXPath.","commonSituations":"Omitting the element name out of habit from :first-child usage; selector linters/normalizers rewriting element names to '*'; auto-generated selectors from recorders.","solutions":["Specify the element type: 'div:first-of-type' instead of '*:first-of-type'.","Use ':first-child' if any element type is acceptable — it works with '*'.","Catch ExpressionErrorException and rewrite or reject the selector.","Note this only applies to XPath-based translation; browsers themselves handle '*:first-of-type'."],"exampleFix":"// before\n'*:first-of-type'\n// after\n'div:first-of-type' // or '*:first-child'","handlingStrategy":"try-catch","validationCode":"if (preg_match('/^\\*:(first|last)-of-type$/', trim($selector))) {\n    throw new \\InvalidArgumentException('Provide a concrete element type with of-type pseudo-classes.');\n}","typeGuard":"function universalWithOfType(string $css): bool {\n    return (bool) preg_match('/(^|[\\s,+>~])\\*:(first|last|only)-(of-type)?/m', $css);\n}","tryCatchPattern":"try {\n    $xpath = $translator->cssToXPath($css);\n} catch (ExpressionErrorException $e) {\n    if (str_contains($e->getMessage(), 'first-of-type')) {\n        $xpath = $translator->cssToXPath(preg_replace('/(^|\\s)\\*:first-of-type/', '$1*:first-child', $css));\n    }\n}","preventionTips":["Use :first-child instead of *:first-of-type when element type is irrelevant.","Always pair *-of-type pseudo-classes with an explicit element name.","Normalize/lint selectors before translation.","Remember this limit is specific to XPath translation, not browser CSS."],"tags":["css-selector","xpath","unsupported-selector"],"backgroundTag":"unsupported-operation","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"}