symfony/css-selector · error · ExpressionErrorException

Expected a single string or identifier for :lang(), got

Error message

Expected a single string or identifier for :lang(), got 

What it means

ExpressionErrorException thrown by FunctionExtension::translateLang (plain XPath extension) when any argument token of :lang() is neither a string nor an identifier. The translator builds a lang(...) XPath condition from a literal value only, so other token types are rejected before the condition is emitted.

Solutions

  1. Quote the language code as a string: ':lang("en")'.
  2. Use a plain identifier: ':lang(en)'.
  3. Pass exactly one language per :lang() and combine selectors for multiple languages: ':lang(en), :lang(fr)'.
  4. Catch ExpressionErrorException and validate :lang() arguments before translating.

Example fix

// before
'p:lang(12)'
// after
'p:lang("en")'
Defensive patterns

Strategy: validation

Validate before calling

foreach ($args as $arg) {
    if (!preg_match('/^("[^"]*"|\'[\w-]*\'|[A-Za-z][\w-]*)$/', $arg)) {
        throw new \InvalidArgumentException(':lang() argument must be a quoted string or identifier.');
    }
}

Try / catch

try {
    $xpath = $translator->cssToXPath($css);
} catch (ExpressionErrorException $e) {
    if (str_contains($e->getMessage(), ':lang()')) {
        // reject selector
    }
}

Prevention

When it happens

Trigger: Translating selectors like 'p:lang(123)', ':lang(en, fr)' where one of the tokens is not string/identifier, or constructing a FunctionNode with non-literal tokens programmatically and running it through Translator::cssToXPath.

Common situations: Unquoted language codes containing characters that tokenize as numbers, generated selectors feeding raw values, confusion with the CSS4 multi-argument :lang() which this library does not support this way.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at XPath/Extension/FunctionExtension.php:151

                throw new ExpressionErrorException('Expected a single string or identifier for :contains(), got '.implode(', ', $arguments));
            }
        }

        return $xpath->addCondition(\sprintf(
            'contains(string(.), %s)',
            Translator::getXpathLiteral($arguments[0]->getValue())
        ));
    }

    /**
     * @throws ExpressionErrorException
     */
    public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr
    {
        $arguments = $function->getArguments();
        foreach ($arguments as $token) {
            if (!($token->isString() || $token->isIdentifier())) {
                throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments));
            }
        }

        return $xpath->addCondition(\sprintf(
            'lang(%s)',
            Translator::getXpathLiteral($arguments[0]->getValue())
        ));
    }

    public function getName(): string
    {
        return 'function';
    }
}

View on GitHub (pinned to 08e2905152)