{"record":{"id":"992dca9ada63bc07","repo":"symfony/css-selector","slug":"string-or-identifier","errorCode":null,"errorMessage":"string or identifier","messagePattern":"string or identifier","errorType":"exception","errorClass":"SyntaxErrorException","httpStatus":null,"severity":"error","filePath":"Parser/Parser.php","lineNumber":465,"sourceCode":"                && $stream->getPeek()->isDelimiter(['='])\n            ) {\n                $operator = $next->getValue().'=';\n                $stream->getNext();\n            } else {\n                throw SyntaxErrorException::unexpectedToken('operator', $next);\n            }\n        }\n\n        $stream->skipWhitespace();\n        $value = $stream->getNext();\n\n        if ($value->isNumber()) {\n            // if the value is a number, it's casted into a string\n            $value = new Token(Token::TYPE_STRING, (string) $value->getValue(), $value->getPosition());\n        }\n\n        if (!($value->isIdentifier() || $value->isString())) {\n            throw SyntaxErrorException::unexpectedToken('string or identifier', $value);\n        }\n\n        $stream->skipWhitespace();\n        $next = $stream->getNext();\n\n        if (!$next->isDelimiter([']'])) {\n            throw SyntaxErrorException::unexpectedToken('\"]\"', $next);\n        }\n\n        return new Node\\AttributeNode($selector, $namespace, $attribute, $operator, $value->getValue());\n    }\n}\n","sourceCodeStart":447,"sourceCodeEnd":478,"githubUrl":"https://github.com/symfony/css-selector/blob/08e2905152a39cf3fd1745d83f8c483e258887d9/Parser/Parser.php#L447-L478","documentation":"This SyntaxErrorException is thrown when the value of an attribute selector comparison is neither an identifier nor a string (numbers are auto-cast to strings, but anything else fails). The parser reports 'Expected string or identifier, but X found.'","triggerScenarios":"Selectors like 'a[href=\"x\"' where a stray token appears in the value position: 'div[data-x=\"a\"b]', '[data-x==\"v\"]', an unquoted value containing invalid characters, or a value built by interpolating non-scalar data (array/null) into the selector string.","commonSituations":"Interpolating PHP variables that json_encode/array-cast oddly into the selector; double quotes inside single-quoted strings or vice versa breaking tokenization; operators accidentally duplicated so the second '=' lands in the value slot.","solutions":["Quote the attribute value: '[data-x=\"value\"]' instead of relying on a raw token in the value position.","Ensure the interpolated value is a scalar and cast it: sprintf('[data-x=\"%s\"]', (string) $value).","Escape embedded quotes, or use single quotes for the CSS string when the value contains double quotes.","Remove duplicated '=' from the operator before the value."],"exampleFix":"// before\n$xpath = $converter->toXPath(sprintf('div[data-id=%s]', $id)); // $id = ['a'] -> invalid token\n\n// after\n$xpath = $converter->toXPath(sprintf('div[data-id=\"%s\"]', (string) $id));","handlingStrategy":"validation","validationCode":"// always quote and escape the value when building attribute selectors\nfunction attrSelector(string $attr, string $op, string $value): string {\n    return sprintf('[%s%s\"%s\"]', $attr, $op, str_replace('\"', '\\\\\"', $value));\n}","typeGuard":"function isQuotableScalar($v): bool {\n    return is_scalar($v);\n}","tryCatchPattern":null,"preventionTips":["Always wrap attribute values in quotes when interpolating variables.","Cast values to string and escape embedded quotes before insertion.","Avoid double operators ('==') which push a stray '=' into the value position."],"tags":["css-selector","attribute-selector","value","php"],"backgroundTag":"invalid-css-selector","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"}