grpc/grpc-java · error · IllegalArgumentException

CEL expression must evaluate to boolean, got:

Error message

CEL expression must evaluate to boolean, got: 

What it means

CelMatcher.compile() validates that the parsed CEL AST's result type is BOOL before creating the evaluation program. gRPC xDS CEL matchers are used as boolean predicates for routing/matching decisions, so a non-boolean expression can never produce a match verdict. The compile step fails fast with IllegalArgumentException naming the actual result type.

Source

Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/CelMatcher.java:44

 * Executes compiled CEL expressions.
 */
final class CelMatcher {
  private final CelRuntime.Program program;

  private CelMatcher(CelRuntime.Program program) {
    this.program = program;
  }

  /**
   * Compiles the AST into a CelMatcher.
   * Throws an Exception if evaluation fails during compilation setup.
   */
  static CelMatcher compile(CelAbstractSyntaxTree ast)
      throws CelEvaluationException {
    // CelEvaluationException -> inside cel-runtime -> Allowed in production signatures
    // CelValidationException -> inside cel-compiler -> Forbidden in production signatures
    if (ast.getResultType() != SimpleType.BOOL) {
      throw new IllegalArgumentException(
          "CEL expression must evaluate to boolean, got: " + ast.getResultType());
    }
    CelCommon.checkAllowedReferences(ast);
    CelRuntime.Program program = CelCommon.RUNTIME.createProgram(ast);
    return new CelMatcher(program);
  }

  /**
   * Evaluates the CEL expression against the input activation.
   */
  boolean match(Object input) throws CelEvaluationException {
    Object result;
    if (input instanceof CelVariableResolver) {
      result = program.eval((CelVariableResolver) input);
    } else {
      throw new CelEvaluationException(
          "Unsupported input type for CEL evaluation: "
               + (input == null ? "null" : input.getClass().getName()));

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Rewrite the CEL expression so it evaluates to bool (add a comparison, e.g. 'req.headers[\"x-user\"] == \"admin\"').
  2. Check ast.getResultType() before compiling and reject the config upstream with a clearer message.
  3. If a string value is needed rather than a boolean predicate, use CelStringExtractor.compile() instead of CelMatcher.compile().

Example fix

// before
CelMatcher.compile(CelCommon.COMPILER.compile("request.headers['x-version']"));
// after
CelMatcher.compile(CelCommon.COMPILER.compile("request.headers['x-version'] == 'v2'"));
Defensive patterns

Strategy: validation

Validate before calling

if (ast.getResultType() != SimpleType.BOOL) {
  throw new IllegalArgumentException("CEL expr must be bool, got: " + ast.getResultType());
}
CelMatcher matcher = CelMatcher.compile(ast);

Type guard

boolean isBoolAst(CelAbstractSyntaxTree ast) { return ast.getResultType() == SimpleType.BOOL; }

Try / catch

try { return CelMatcher.compile(ast); }
catch (IllegalArgumentException e) { logger.warn("non-boolean CEL expr", e); return null; }

Prevention

When it happens

Trigger: Calling CelMatcher.compile(ast) with an AST whose getResultType() is not SimpleType.BOOL, e.g. a CEL expression like 'request.headers["x"]' (string) or '1 + 2' (int) instead of a predicate like 'request.headers["x"] == "y"'.

Common situations: xDS config carrying a CelMatcher whose expr was written as a value expression rather than a boolean comparison; copy-pasting extractor-style expressions (string-typed) into a match context; schema changes where the checked expression type was relaxed or mistyped.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/4ec4729b34ae4961. Report an issue: GitHub.