symfony/css-selector · error · ExpressionErrorException
Attribute matcher operator
Error message
Attribute matcher operator "%s" not supported.
What it means
Translator::addAttributeMatching() dispatches an attribute matcher operator (=, ^=, $=, *=, ~=, |=) to a handler in $this->attributeMatchingTranslators and throws ExpressionErrorException when the operator is unknown. The operator normally comes from parsed Attribute nodes, so valid CSS never triggers this — it is a guard for the extension/programmatic API.
Solutions
- Use a standard CSS attribute operator: =, ^=, $=, *=, ~=, |=.
- Register a custom attribute matching translator via Translator::extension() for non-standard operators.
- Verify the operator value produced by the parser for the attribute selector in question.
Example fix
// before $translator->addAttributeMatching($xpath, '!==', 'href', 'x'); // unknown operator, throws // after $translator->addAttributeMatching($xpath, '!=', 'href', 'x'); // only if registered, else use '=' and filter // safest: use a supported operator $translator->addAttributeMatching($xpath, '=', 'href', 'x');
Defensive patterns
Strategy: validation
Validate before calling
const VALID_ATTR_OPS = ['=', '^=', '$=', '*=', '~=', '!=', '|='];
if (!in_array($operator, self::VALID_ATTR_OPS, true)) {
throw new \InvalidArgumentException("Invalid attribute operator: $operator");
} Try / catch
use Symfony\Component\CssSelector\Exception\ExpressionErrorException;
try {
$expr = $translator->addAttributeMatching($xpath, $op, $attr, $value);
} catch (ExpressionErrorException $e) {
// coerce to '=' or skip the attribute condition
} Prevention
- Only construct Attribute nodes with operators from the standard CSS set
- Sanitize operators parsed from custom selector dialects
- Cover each operator path with unit tests so regressions surface early
When it happens
Trigger: Calling addAttributeMatching() with an $operator string not among the registered matchers (e.g. '!==' or an empty string), typically from custom node construction or a test such as testAddAttributeMatchingClassNotExistsClass.
Common situations: Programmatic XPathExpr/Attribute node building with an invalid operator; custom selector dialects with new operators lacking a registered matcher; corrupted tokenization upstream.
Related errors
- Combiner " " not supported.
- "*:nth-of-type()" is not implemented.
- "*:first-of-type" is not implemented.
- "*:last-of-type" is not implemented.
- Pseudo-elements are not supported.
AI-assisted analysis of symfony/css-selector@08e2905152 (2026-09-14).
Data as JSON: /api/errors/56298f64e6d2b31d.
Report an issue: GitHub.
Appendix: source
Thrown at XPath/Translator.php:217
/**
* @throws ExpressionErrorException
*/
public function addPseudoClass(XPathExpr $xpath, string $pseudoClass): XPathExpr
{
if (!isset($this->pseudoClassTranslators[$pseudoClass])) {
throw new ExpressionErrorException(\sprintf('Pseudo-class "%s" not supported.', $pseudoClass));
}
return $this->pseudoClassTranslators[$pseudoClass]($xpath);
}
/**
* @throws ExpressionErrorException
*/
public function addAttributeMatching(XPathExpr $xpath, string $operator, string $attribute, ?string $value): XPathExpr
{
if (!isset($this->attributeMatchingTranslators[$operator])) {
throw new ExpressionErrorException(\sprintf('Attribute matcher operator "%s" not supported.', $operator));
}
return $this->attributeMatchingTranslators[$operator]($xpath, $attribute, $value);
}
/**
* @return SelectorNode[]
*/
private function parseSelectors(string $css): array
{
foreach ($this->shortcutParsers as $shortcut) {
$tokens = $shortcut->parse($css);
if ($tokens) {
return $tokens;
}
}
View on GitHub (pinned to 08e2905152)