{"record":{"id":"d320cce420565a0d","repo":"symfony/css-selector","slug":"expected-a-single-string-or-identifier-for-contains-got","errorCode":null,"errorMessage":"Expected a single string or identifier for :contains(), got ","messagePattern":"Expected a single string or identifier for :contains\\(\\), got ","errorType":"exception","errorClass":"ExpressionErrorException","httpStatus":null,"severity":"error","filePath":"XPath/Extension/FunctionExtension.php","lineNumber":133,"sourceCode":"     */\n    public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr\n    {\n        if ('*' === $xpath->getElement()) {\n            throw new ExpressionErrorException('\"*:nth-of-type()\" is not implemented.');\n        }\n\n        return $this->translateNthChild($xpath, $function, true, false);\n    }\n\n    /**\n     * @throws ExpressionErrorException\n     */\n    public function translateContains(XPathExpr $xpath, FunctionNode $function): XPathExpr\n    {\n        $arguments = $function->getArguments();\n        foreach ($arguments as $token) {\n            if (!($token->isString() || $token->isIdentifier())) {\n                throw new ExpressionErrorException('Expected a single string or identifier for :contains(), got '.implode(', ', $arguments));\n            }\n        }\n\n        return $xpath->addCondition(\\sprintf(\n            'contains(string(.), %s)',\n            Translator::getXpathLiteral($arguments[0]->getValue())\n        ));\n    }\n\n    /**\n     * @throws ExpressionErrorException\n     */\n    public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr\n    {\n        $arguments = $function->getArguments();\n        foreach ($arguments as $token) {\n            if (!($token->isString() || $token->isIdentifier())) {\n                throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments));","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/symfony/css-selector/blob/08e2905152a39cf3fd1745d83f8c483e258887d9/XPath/Extension/FunctionExtension.php#L115-L151","documentation":"ExpressionErrorException thrown by FunctionExtension::translateContains when any argument token of :contains() is neither a string nor an identifier token. :contains() translates to an XPath contains(string(.), ...) condition that only accepts literal values, so any other token type (e.g. a dimension, number, hash, or operator token) is rejected.","triggerScenarios":"Translating selectors like 'div:contains(42)' where 42 parses as a number token, 'div:contains(\"a\" \"b\")' with multiple non-identifier arguments, or 'div:contains()' referencing a token of the wrong type at index 0 when building the condition.","commonSituations":"Programmatic selector construction that passes numeric values unquoted, mistyping the argument so the tokenizer classifies it as a number/percentage, injection of unusual characters that change token classification.","solutions":["Quote the argument as a string: 'div:contains(\"42\")' instead of 'div:contains(42)'.","Use a bare identifier (letters) if a quoted string is not required: 'div:contains(Warning)'.","Catch ExpressionErrorException around cssToXPath and surface a clear invalid-selector message.","Pre-validate :contains() arguments in generated selectors to ensure they are quoted strings or plain identifiers."],"exampleFix":"// before\n'div:contains(42)'\n// after\n'div:contains(\"42\")'","handlingStrategy":"validation","validationCode":"foreach ($args as $arg) {\n    if (!preg_match('/^(\"[^\"]*\"|\\'[\\w\\s-]*\\'|[A-Za-z][\\w-]*)$/', $arg)) {\n        throw new \\InvalidArgumentException(':contains() argument must be a quoted string or identifier.');\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    $xpath = $translator->cssToXPath($css);\n} catch (ExpressionErrorException $e) {\n    if (str_contains($e->getMessage(), ':contains()')) {\n        // reject selector\n    }\n}","preventionTips":["Always quote :contains() text values.","Keep :contains() to a single string/identifier argument.","Escape embedded quotes in generated selectors.","Avoid passing numeric values without quotes."],"tags":["css-selector","contains","argument-validation"],"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"}