grpc/grpc-java · error · IllegalArgumentException

CelMatcher must have cel_expr_checked

Error message

CelMatcher must have cel_expr_checked

What it means

After confirming expr_match is present, getMatcher() requires the CelExpression to contain cel_expr_checked — the type-checked AST form produced by cel compile's CheckedExpr. Without it there is no AST to convert via CelProtoAbstractSyntaxTree.fromCheckedExpr, so the config is rejected.

Source

Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/CelStateMatcher.java:61

  }

  @Override
  public Class<?> inputType() {
    return GrpcCelEnvironment.class;
  }

  static final class Provider implements MatcherProvider {
    @Override
    public CelStateMatcher getMatcher(TypedExtensionConfig config) {
      try {
        com.github.xds.type.matcher.v3.CelMatcher celProto = config.getTypedConfig()
            .unpack(com.github.xds.type.matcher.v3.CelMatcher.class);
        if (!celProto.hasExprMatch()) {
          throw new IllegalArgumentException("CelMatcher must have expr_match");
        }
        CelExpression expr = celProto.getExprMatch();
        if (!expr.hasCelExprChecked()) {
          throw new IllegalArgumentException("CelMatcher must have cel_expr_checked");
        }
        CelAbstractSyntaxTree ast = 
            CelProtoAbstractSyntaxTree.fromCheckedExpr(
                expr.getCelExprChecked()).getAst();
        CelMatcher compiled = CelMatcher.compile(ast);
        
        return new CelStateMatcher(compiled);
      } catch (Exception e) {
        throw new IllegalArgumentException("Invalid CelMatcher config", e);
      }
    }

    @Override
    public String typeUrl() {
      return TYPE_URL;
    }
  }
}

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Type-check the expression with the CEL compiler and embed the result via setCelExprChecked(CheckedExpr).
  2. Verify proto.hasCelExprChecked() on the producer side before emitting the config.
  3. NACK the xDS config at the management layer with an explanation that only checked expressions are supported.

Example fix

// before
CelExpression.newBuilder().setCelExpr(parsedExpr).build();
// after
CelExpression.newBuilder().setCelExprChecked(checkOutput.getExprChecked()).build();
Defensive patterns

Strategy: validation

Validate before calling

if (!expr.hasCelExprChecked()) {
  throw new IllegalArgumentException("cel_expr_checked required; run CEL checker first");
}

Type guard

boolean hasCheckedExpr(CelExpression expr) { return expr.hasCelExprChecked(); }

Try / catch

try { return factory.getMatcher(config); }
catch (IllegalArgumentException e) { nackConfig(config, "cel_expr_checked missing"); return null; }

Prevention

When it happens

Trigger: expr_match is set but only holds unchecked/parsed CelExpr (or is empty), so expr.hasCelExprChecked() is false when getMatcher() unpacks the config.

Common situations: Clients sending source text or unchecked expressions instead of running the CEL checker and embedding CheckedExpr; tooling that serializes ParseOutput rather than CheckOutput; partially populated protos from hand-rolled builders.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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