symfony/css-selector · error · ExpressionErrorException
"*:first-of-type" is not implemented.
Error message
"*:first-of-type" is not implemented.
What it means
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'.
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'.
Example fix
// before '*:first-of-type' // after 'div:first-of-type' // or '*:first-child'
Defensive patterns
Strategy: try-catch
Validate before calling
if (preg_match('/^\*:(first|last)-of-type$/', trim($selector))) {
throw new \InvalidArgumentException('Provide a concrete element type with of-type pseudo-classes.');
} Type guard
function universalWithOfType(string $css): bool {
return (bool) preg_match('/(^|[\s,+>~])\*:(first|last|only)-(of-type)?/m', $css);
} Try / catch
try {
$xpath = $translator->cssToXPath($css);
} catch (ExpressionErrorException $e) {
if (str_contains($e->getMessage(), 'first-of-type')) {
$xpath = $translator->cssToXPath(preg_replace('/(^|\s)\*:first-of-type/', '$1*:first-child', $css));
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Omitting the element name out of habit from :first-child usage; selector linters/normalizers rewriting element names to '*'; auto-generated selectors from recorders.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- "*:nth-of-type()" is not implemented.
- "*:last-of-type" is not implemented.
- Pseudo-class " " not supported.
- Pseudo-elements are not supported.
- Node " " not supported.
AI-assisted analysis of symfony/css-selector@08e2905152 (2026-09-14).
Data as JSON: /api/errors/45132e37aadf4b14.
Report an issue: GitHub.
Appendix: source
Thrown at XPath/Extension/PseudoClassExtension.php:76
->addNameTest()
->addCondition('position() = 1');
}
public function translateLastChild(XPathExpr $xpath): XPathExpr
{
return $xpath
->addStarPrefix()
->addNameTest()
->addCondition('position() = last()');
}
/**
* @throws ExpressionErrorException
*/
public function translateFirstOfType(XPathExpr $xpath): XPathExpr
{
if ('*' === $xpath->getElement()) {
throw new ExpressionErrorException('"*:first-of-type" is not implemented.');
}
return $xpath
->addStarPrefix()
->addCondition('position() = 1');
}
/**
* @throws ExpressionErrorException
*/
public function translateLastOfType(XPathExpr $xpath): XPathExpr
{
if ('*' === $xpath->getElement()) {
throw new ExpressionErrorException('"*:last-of-type" is not implemented.');
}
return $xpath
->addStarPrefix()View on GitHub (pinned to 08e2905152)