{"record":{"id":"31858b3a7a4fa405","repo":"symfony/css-selector","slug":"string-not-allowed-as-function-argument","errorCode":null,"errorMessage":"String not allowed as function argument.","messagePattern":"String not allowed as function argument\\.","errorType":"exception","errorClass":"SyntaxErrorException","httpStatus":null,"severity":"error","filePath":"Parser/Parser.php","lineNumber":62,"sourceCode":"    {\n        $reader = new Reader($source);\n        $stream = $this->tokenizer->tokenize($reader);\n\n        return $this->parseSelectorList($stream);\n    }\n\n    /**\n     * Parses the arguments for \":nth-child()\" and friends.\n     *\n     * @param Token[] $tokens\n     *\n     * @throws SyntaxErrorException\n     */\n    public static function parseSeries(array $tokens): array\n    {\n        foreach ($tokens as $token) {\n            if ($token->isString()) {\n                throw SyntaxErrorException::stringAsFunctionArgument();\n            }\n        }\n\n        $joined = trim(implode('', array_map(static fn (Token $token) => $token->getValue(), $tokens)));\n\n        $int = static function ($string) {\n            if (!is_numeric($string)) {\n                throw SyntaxErrorException::stringAsFunctionArgument();\n            }\n\n            return (int) $string;\n        };\n\n        switch (true) {\n            case 'odd' === $joined:\n                return [2, 1];\n            case 'even' === $joined:\n                return [2, 0];","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/symfony/css-selector/blob/08e2905152a39cf3fd1745d83f8c483e258887d9/Parser/Parser.php#L44-L80","documentation":"Parser::parseSeries() parses the (an? b?) argument of :nth-child()/:nth-last-child() pseudo-classes. Before numeric parsing it rejects any Token of TYPE_STRING with SyntaxErrorException::stringAsFunctionArgument(), because quoted values are never valid inside these functional pseudo-classes.","triggerScenarios":"Calling parseSeries() (directly, as in testParseSeriesException, or via nth-child translation) with a token stream containing a string token — e.g. a selector like :nth-child(\"2\") where the argument was tokenized as a string.","commonSituations":"Programmatic token construction that wrapped the nth argument in quotes; templates interpolating quoted values into :nth-child(); misunderstanding that nth arguments are plain numbers/identifiers, not strings.","solutions":["Remove the quotes from the nth-child argument: :nth-child(\"2\") becomes :nth-child(2).","When building tokens programmatically, emit TYPE_NUMBER or TYPE_IDENTIFIER tokens instead of TYPE_STRING for the argument.","Validate the argument shape (integer or 'odd'/'even'/'an+b') before passing to parseSeries()."],"exampleFix":"// before\n$css = 'li:nth-child(\"2\")'; // string token, throws\n\n// after\n$css = 'li:nth-child(2)'; // bare argument","handlingStrategy":"validation","validationCode":"// nth arguments must be bare, not quoted\nif (!preg_match('/^:(?:nth-(?:last-)?(?:child|of-type))\\(\\s*(?:odd|even|-?\\d+n?(?:\\s*[+-]\\s*\\d+)?)\\s*\\)$/i', $pseudoSelector)) {\n    throw new \\InvalidArgumentException('Invalid :nth-child argument (must be unquoted an+b / odd / even)');\n}","typeGuard":null,"tryCatchPattern":"use Symfony\\Component\\CssSelector\\Exception\\SyntaxErrorException;\ntry {\n    [$a, $b] = Parser::parseSeries($tokens);\n} catch (SyntaxErrorException $e) {\n    // reject selector or fall back to a simpler child selector\n}","preventionTips":["Never quote :nth-child arguments; interpolate numbers directly","Pre-validate an+b expressions with a regex before parsing","When constructing tokens programmatically, use NUMBER/IDENTIFIER token types, never STRING"],"tags":["css-selector","parser","nth-child","syntax-error"],"backgroundTag":"invalid-argument-value","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"}