grpc/grpc-java · error · IllegalArgumentException
CelMatcher must have expr_match
Error message
CelMatcher must have expr_match
What it means
CelStateMatcher.getMatcher() unpacks the TypedExtensionConfig's typed_config as an xDS CelMatcher proto and requires the expr_match field to be set. A CelMatcher proto without expr_match carries no CEL expression at all, so no matcher can be built. The factory rejects such configs with IllegalArgumentException.
Source
Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/CelStateMatcher.java:57
return compiledEndpoint.match(value);
} catch (CelEvaluationException e) {
return false;
}
}
@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() {View on GitHub (pinned to 64daddc1f3)
Solutions
- Populate expr_match in the CelMatcher proto before sending the config (proto.hasExprMatch() must be true).
- Validate the extension config on the control plane side prior to xDS delivery.
- Catch IllegalArgumentException from getMatcher() and reject the whole config with an NACK / clearer error.
Example fix
// before
CelMatcher.newBuilder().build(); // expr_match missing
// after
CelMatcher.newBuilder()
.setExprMatch(CelExpression.newBuilder().setCelExprChecked(checkedExpr))
.build(); Defensive patterns
Strategy: validation
Validate before calling
CelMatcherProto.CelMatcher celProto =
config.getTypedConfig().unpack(CelMatcherProto.CelMatcher.class);
if (!celProto.hasExprMatch()) throw new IllegalArgumentException("expr_match required"); Type guard
boolean hasExprMatch(TypedExtensionConfig config) {
return config.getTypedConfig().is(CelMatcherProto.CelMatcher.class)
&& unpackSafe(config).hasExprMatch();
} Try / catch
try { return factory.getMatcher(config); }
catch (IllegalArgumentException e) { nackConfig(config, "expr_match missing: " + e.getMessage()); return null; } Prevention
- Validate matcher protos control-plane side before xDS push.
- Use proto builder setters (setExprMatch) so field presence is explicit.
- Add fixture tests that round-trip matcher configs through serialization.
When it happens
Trigger: An xDS TypedExtensionConfig whose typed_config is type.googleapis.com/xds.type.matcher.v3.CelMatcher but with expr_match unset (oneof empty) reaches getMatcher().
Common situations: Control plane emitting CelMatcher protos with only defaults populated; hand-written test fixtures forgetting to call setExprMatch(); proto field name changes across xDS type versions.
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
- CelMatcher must have cel_expr_checked
- Invalid CelMatcher config
- CEL expression must evaluate to boolean, got:
- Unsupported input type for CEL evaluation:
- CEL expression must evaluate to string, got: ${ast.getResult
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/30ca2741b9a9d0b8.
Report an issue: GitHub.