symfony/css-selector · error · ExpressionErrorException

Invalid series: " ".

Error message

Invalid series: "%s".

What it means

ExpressionErrorException thrown by FunctionExtension::translateNthChild when Parser::parseSeries cannot extract valid (a, b) coefficients from the arguments of :nth-child(), :nth-last-child(), :nth-of-type(), or :nth-last-of-type(). parseSeries throws SyntaxErrorException for malformed An+B expressions; this wraps it with the offending argument list.

Solutions

  1. Fix the selector's nth expression to a valid An+B form: integer, 'odd', 'even', 'an', 'an+b', '-an+b', 'n', '2n+1', etc.
  2. Catch Symfony\Component\CssSelector\Exception\ExpressionErrorException around the translation call.
  3. Validate the nth argument with a regex such as /^([+-]?\d*n)?\s*([+-]\s*\d+)?$/ before translating.
  4. Upgrade the library — some edge-case series parse failures were fixed in newer css-selector releases.

Example fix

// before
'li:nth-child(2 n + 1)'
// after
'li:nth-child(2n+1)'
Defensive patterns

Strategy: validation

Validate before calling

function isValidAnB(?string $expr): bool {
    return null !== $expr && (bool) preg_match('/^([+-]?\d*n)?\s*([+-]\s*\d+)?$|^odd$|^even$/i', trim($expr));
}
// validate each :nth-child() argument before cssToXPath

Try / catch

try {
    $xpath = $translator->cssToXPath($css);
} catch (\Symfony\Component\CssSelector\Exception\ExpressionErrorException $e) {
    if (str_starts_with($e->getMessage(), 'Invalid series:')) {
        // fix or reject the nth expression
    }
}

Prevention

When it happens

Trigger: Translating a selector like li:nth-child(odd extra), li:nth-child(n+b+1), li:nth-child(1.5n), or an empty :nth-child() — any argument that is not a valid 'an+b' series — via Translator::cssToXPath.

Common situations: Typos in hand-written selectors, localized 'odd/even' spelled differently, user-supplied selectors with invalid formulas, passing values like 'even,' with stray commas.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of symfony/css-selector@08e2905152 (2026-09-14). Data as JSON: /api/errors/efba73c3108c415f. Report an issue: GitHub.

Appendix: source

Thrown at XPath/Extension/FunctionExtension.php:53

        return [
            'nth-child' => $this->translateNthChild(...),
            'nth-last-child' => $this->translateNthLastChild(...),
            'nth-of-type' => $this->translateNthOfType(...),
            'nth-last-of-type' => $this->translateNthLastOfType(...),
            'contains' => $this->translateContains(...),
            'lang' => $this->translateLang(...),
        ];
    }

    /**
     * @throws ExpressionErrorException
     */
    public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr
    {
        try {
            [$a, $b] = Parser::parseSeries($function->getArguments());
        } catch (SyntaxErrorException $e) {
            throw new ExpressionErrorException(\sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e);
        }

        $xpath->addStarPrefix();
        if ($addNameTest) {
            $xpath->addNameTest();
        }

        if (0 === $a) {
            return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b));
        }

        if ($a < 0) {
            if ($b < 1) {
                return $xpath->addCondition('false()');
            }

            $sign = '<=';
        } else {

View on GitHub (pinned to 08e2905152)