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

  1. Specify the element type: 'div:first-of-type' instead of '*:first-of-type'.
  2. Use ':first-child' if any element type is acceptable — it works with '*'.
  3. Catch ExpressionErrorException and rewrite or reject the selector.
  4. 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

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


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)