{"record":{"id":"13f257d0d8d1d454","repo":"symfony/css-selector","slug":"last-of-type-is-not-implemented","errorCode":null,"errorMessage":"\"*:last-of-type\" is not implemented.","messagePattern":"\"\\*:last-of-type\" is not implemented\\.","errorType":"exception","errorClass":"ExpressionErrorException","httpStatus":null,"severity":"error","filePath":"XPath/Extension/PseudoClassExtension.php","lineNumber":90,"sourceCode":"     */\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()\n            ->addCondition('position() = last()');\n    }\n\n    public function translateOnlyChild(XPathExpr $xpath): XPathExpr\n    {\n        return $xpath\n            ->addStarPrefix()\n            ->addNameTest()\n            ->addCondition('last() = 1');\n    }\n\n    public function translateOnlyOfType(XPathExpr $xpath): XPathExpr\n    {\n        $element = $xpath->getElement();","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/symfony/css-selector/blob/08e2905152a39cf3fd1745d83f8c483e258887d9/XPath/Extension/PseudoClassExtension.php#L72-L108","documentation":"ExpressionErrorException thrown by PseudoClassExtension::translateLastOfType when the XPath element is '*'. Like :first-of-type, 'last element of its type' cannot be expressed against a universal selector, so '*:last-of-type' is rejected outright.","triggerScenarios":"Translating '*:last-of-type' or selectors normalized so the element is '*' with :last-of-type attached, via Translator::cssToXPath.","commonSituations":"Same confusion as with :first-of-type/:nth-last-of-type — using of-type pseudo-classes without a type selector; auto-generated or minified selectors losing the element name.","solutions":["Replace '*' with a concrete element type: 'tr:last-of-type'.","Use ':last-child' when any element type is acceptable.","Catch ExpressionErrorException and handle the selector at the application level.","Pre-process selectors to detect '*:last-of-type' before calling cssToXPath."],"exampleFix":"// before\n'*:last-of-type'\n// after\n'tr:last-of-type' // or '*:last-child'","handlingStrategy":"try-catch","validationCode":"if (preg_match('/^\\*:last-of-type$/', trim($selector))) {\n    throw new \\InvalidArgumentException('Provide a concrete element type with :last-of-type.');\n}","typeGuard":"function universalLastOfType(string $css): bool {\n    return (bool) preg_match('/(^|[\\s,+>~])\\*:last-of-type/', $css);\n}","tryCatchPattern":"try {\n    $xpath = $translator->cssToXPath($css);\n} catch (ExpressionErrorException $e) {\n    if (str_contains($e->getMessage(), 'last-of-type')) {\n        $xpath = $translator->cssToXPath(str_replace('*:last-of-type', '*:last-child', $css));\n    }\n}","preventionTips":["Prefer :last-child over *:last-of-type.","Attach :last-of-type only to concrete element selectors.","Add selector lint rules banning '*:last-of-type'.","Cover translator edge cases with unit tests."],"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"}