{"record":{"id":"8fb480c4c82f0b39","repo":"symfony/css-selector","slug":"identifier-or","errorCode":null,"errorMessage":"identifier or \"*\"","messagePattern":"identifier or \"\\*\"","errorType":"exception","errorClass":"SyntaxErrorException","httpStatus":null,"severity":"error","filePath":"Parser/TokenStream.php","lineNumber":142,"sourceCode":"\n    /**\n     * Returns next identifier or null if star delimiter token is found.\n     *\n     * @throws SyntaxErrorException If next token is not an identifier or a star delimiter\n     */\n    public function getNextIdentifierOrStar(): ?string\n    {\n        $next = $this->getNext();\n\n        if ($next->isIdentifier()) {\n            return $next->getValue();\n        }\n\n        if ($next->isDelimiter(['*'])) {\n            return null;\n        }\n\n        throw SyntaxErrorException::unexpectedToken('identifier or \"*\"', $next);\n    }\n\n    /**\n     * Skips next whitespace if any.\n     */\n    public function skipWhitespace(): void\n    {\n        $peek = $this->getPeek();\n\n        if ($peek->isWhitespace()) {\n            $this->getNext();\n        }\n    }\n}\n","sourceCodeStart":124,"sourceCodeEnd":157,"githubUrl":"https://github.com/symfony/css-selector/blob/08e2905152a39cf3fd1745d83f8c483e258887d9/Parser/TokenStream.php#L124-L157","documentation":"TokenStream::getNextIdentifierOrStar() consumes the next token and accepts either an identifier token (returns its value) or a '*' delimiter token (returns null, the universal-selector / namespace-wildcard case). Any other token triggers SyntaxErrorException::unexpectedToken('identifier or \"*\"', $next), a CssSelector SyntaxErrorException stating that an identifier or '*' was expected.","triggerScenarios":"Calling getNextIdentifierOrStar() (used for namespace prefixes / universal selector positions, e.g. in '*|div', '|div', 'ns|div') when the next token is neither an identifier nor a '*': e.g. the selector contains a stray character like ':' or ')' or a string where a namespace prefix or '*' should be.","commonSituations":"Selectors with malformed namespace syntax such as 'div|' or '|*|p'; typos like 'div||span'; selectors built dynamically where the namespace variable is empty or contains characters the tokenizer classifies as a string/delimiter; migrating selectors between libraries whose tokenizers differ slightly.","solutions":["Correct the selector so the position holds either a valid identifier or a single '*' (e.g. 'ns|div', '*|div', '|div' — not 'div|' or '||').","If a namespace prefix comes from a variable, verify it is non-empty and matches ident rules before interpolation.","Read the exception message to see the offending token and expected 'identifier or \"*\"' at that stream position.","If consuming the stream directly, guard with $stream->getPeek() and check isIdentifier() or isDelimiter(['*']) before calling.","Catch SyntaxErrorException around selector parsing and reject/handle invalid input cleanly."],"exampleFix":"// before: empty namespace prefix leaves an illegal token where 'identifier or \"*\"' is required\n$filter = \"$ns|li\"; // $ns === ''\n$crawler->filter($filter);\n\n// after: use the universal-namespace '*' when no prefix applies\n$filter = ($ns !== '' ? $ns : '*') . '|li';\n$crawler->filter($filter);","handlingStrategy":"validation","validationCode":"use Symfony\\Component\\CssSelector\\Parser\\TokenStream;\n\nfunction nextTokenIsIdentifierOrStar(TokenStream $stream): bool\n{\n    $peek = $stream->getPeek();\n\n    return $peek->isIdentifier() || $peek->isDelimiter(['*']);\n}\n\n// Namespace prefix validation for dynamic selectors\nfunction isValidNamespacePrefix(?string $ns): bool\n{\n    return $ns === null || $ns === '*' || preg_match('/^[A-Za-z_][A-Za-z0-9_-]*$/', $ns) === 1;\n}","typeGuard":"function isIdentifierOrStarToken(Symfony\\Component\\CssSelector\\Parser\\Token $t): bool\n{\n    return $t->isIdentifier() || $t->isDelimiter(['*']);\n}","tryCatchPattern":"try {\n    $prefix = $stream->getNextIdentifierOrStar();\n} catch (Symfony\\Component\\CssSelector\\Exception\\SyntaxErrorException $e) {\n    // Expected 'identifier or \"*\"'; handle malformed namespace/universal selector\n    throw new InvalidArgumentException('Invalid selector prefix: ' . $e->getMessage(), 0, $e);\n}","preventionTips":["When building 'prefix|name' selectors, default an empty prefix to '*' instead of leaving an empty token.","Test generated selectors with namespace combinations ('ns|div', '*|div', '|div') in unit tests.","Use getPeek() to check isIdentifier()/isDelimiter(['*']) before consuming when writing custom grammar handlers.","Catch SyntaxErrorException at the selector-entry boundary so malformed input never escapes as a crash.","Avoid hand-assembling namespace syntax; use CssSelector's full parser instead of string concatenation where possible."],"tags":["php","css-selector","syntax-error","tokenizer","namespaces"],"backgroundTag":"invalid-identifier","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"}