symfony/css-selector · error · ExpressionErrorException

Node " " not supported.

Error message

Node "%s" not supported.

What it means

Translator::nodeToXPath() dispatches a selector AST node to a registered node translator via $this->nodeTranslators, keyed by the node's name (getNodeName()). If the node name has no registered translator, an ExpressionErrorException is thrown. In practice this only happens when a custom NodeInterface implementation is fed to the translator, since the parser only produces node types the default translator map covers.

Solutions

  1. Register a translator for the node by adding an extension that maps the node name to a callable in nodeTranslators.
  2. Only feed the translator nodes produced by Symfony\Component\CssSelector\Node nodes from the bundled parser, not custom or foreign node objects.
  3. Verify getNodeName() of the offending node matches an existing translator key (e.g. 'Element', 'Class', 'Identifier', 'Attribute', 'CombinedSelector', 'Function', 'Hash', 'PseudoClass', 'Selector', 'Root').

Example fix

// before
$translator->selectorToXPath(new MyCustomNode()); // throws

// after
$translator = $translator->extension(new MyNodeExtension()); // registers translator for the custom node
$translator->selectorToXPath(new MyCustomNode()); // works
Defensive patterns

Strategy: try-catch

Validate before calling

// before translating
if (!in_array($node->getNodeName(), ['Element','Identifier','Attribute','Class','Hash','CombinedSelector','Function','PseudoClass','Selector','Root'], true)) {
    throw new \InvalidArgumentException('Unsupported node: ' . $node->getNodeName());
}

Type guard

function isTranslatableNode(Symfony\Component\CssSelector\Node\NodeInterface $node): bool {
    return isset($this->nodeTranslators[$node->getNodeName()]);
}

Try / catch

use Symfony\Component\CssSelector\Exception\ExpressionErrorException;
try {
    $xpath = $translator->selectorToXPath($selector);
} catch (ExpressionErrorException $e) {
    // log unsupported node, skip or fall back to a simpler selector
}

Prevention

When it happens

Trigger: Calling Translator::nodeToXPath() (directly or via selectorToXPath / addCombination / addRelativeCombination) with a NodeInterface whose getNodeName() is not a key in the translator's nodeTranslators map — e.g. a custom node class or a node from a mismatched parser version.

Common situations: Custom CSS selector extensions that add new AST node types without registering a node translator via Translator::extension(); passing hand-built node objects to selectorToXPath(); upgrading Symfony CssSelector so parser node names no longer match a customized translator map.

Related errors


AI-assisted analysis of symfony/css-selector@08e2905152 (2026-09-14). Data as JSON: /api/errors/85881ecb774e550f. Report an issue: GitHub.

Appendix: source

Thrown at XPath/Translator.php:157

    }

    /**
     * @return $this
     */
    public function registerParserShortcut(ParserInterface $shortcut): static
    {
        $this->shortcutParsers[] = $shortcut;

        return $this;
    }

    /**
     * @throws ExpressionErrorException
     */
    public function nodeToXPath(NodeInterface $node): XPathExpr
    {
        if (!isset($this->nodeTranslators[$node->getNodeName()])) {
            throw new ExpressionErrorException(\sprintf('Node "%s" not supported.', $node->getNodeName()));
        }

        return $this->nodeTranslators[$node->getNodeName()]($node, $this);
    }

    /**
     * @throws ExpressionErrorException
     */
    public function addCombination(string $combiner, NodeInterface $xpath, NodeInterface $combinedXpath): XPathExpr
    {
        if (!isset($this->combinationTranslators[$combiner])) {
            throw new ExpressionErrorException(\sprintf('Combiner "%s" not supported.', $combiner));
        }

        return $this->combinationTranslators[$combiner]($this->nodeToXPath($xpath), $this->nodeToXPath($combinedXpath));
    }

    /**

View on GitHub (pinned to 08e2905152)