grpc/grpc-java · error · IllegalArgumentException
HttpAttributesCelMatchInput cannot be used with MatcherTree
Error message
HttpAttributesCelMatchInput cannot be used with MatcherTree
What it means
MatcherTree matches on a single scalar key derived from its input; HttpAttributesCelMatchInput (a CEL-based multi-attribute input) is incompatible with tree matching, so the constructor rejects it explicitly. Use it with MatcherList predicates instead, where multiple CEL expressions can be evaluated.
Solutions
- Replace the input with a single-key input like HttpRequestHeaderMatchInput.
- Move the CEL expression into a MatcherList FieldMatcher predicate (custom_match with CelMatchInput) instead of a MatcherTree.
- If tree semantics are required, compute the key upstream (e.g. into a header) and match on that header.
Example fix
// before
{"matcher_tree": {"input": {"typed_config": {"@type": ".../HttpAttributesCelMatchInput"}}, "exact_match_map": {...}}}
// after
{"matcher_tree": {"input": {"typed_config": {"@type": ".../HttpRequestHeaderMatchInput", "header_name": "x-key"}}, "exact_match_map": {...}}} Defensive patterns
Strategy: validation
Validate before calling
String typeUrl = treeProto.getInput().getTypedConfig().getTypeUrl();
if (typeUrl.endsWith("HttpAttributesCelMatchInput")) {
throw new IllegalArgumentException("HttpAttributesCelMatchInput is not valid for MatcherTree");
} Type guard
boolean isTreeCompatibleInput(TypedExtensionConfig input) {
return !input.getTypedConfig().getTypeUrl().endsWith("HttpAttributesCelMatchInput");
} Try / catch
try {
matcherTree = new MatcherTree(proto, onNoMatch, validator);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("HttpAttributesCelMatchInput")) {
// rewrite as MatcherList with CEL predicate
}
throw e;
} Prevention
- Use HttpRequestHeaderMatchInput (or similar single-key input) for MatcherTree
- Reserve CEL input for MatcherList predicates
- Document input-to-tree compatibility in config templates
When it happens
Trigger: Constructing MatcherTree whose input TypedExtensionConfig type_url equals TYPE_URL_HTTP_ATTRIBUTES_CEL_INPUT (HttpAttributesCelMatchInput).
Common situations: Reusing the same input config block when switching a matcher from list form to tree form; copying an Envoy config that uses CEL input with a list matcher into a tree matcher.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- AndMatcher must have at least 2 predicates
- MatcherList must contain at least one FieldMatcher
- MatcherTree does not support custom_match
- MatcherTree exact_match_map must contain at least one entry
- MatcherTree must have either exact_match_map or…
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/98e94d380f4f3714.
Report an issue: GitHub.
Appendix: source
Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/MatcherTree.java:47
final class MatcherTree extends UnifiedMatcher {
private static final String TYPE_URL_HTTP_ATTRIBUTES_CEL_INPUT =
"type.googleapis.com/xds.type.matcher.v3.HttpAttributesCelMatchInput";
private final MatchInput input;
@Nullable
private final Map<String, OnMatch> exactMatchMap;
@Nullable
private final PrefixTrie prefixTrie;
@Nullable
private final OnMatch onNoMatch;
MatcherTree(Matcher.MatcherTree proto, @Nullable Matcher.OnMatch onNoMatchProto,
Predicate<String> actionValidator) {
if (!proto.hasInput()) {
throw new IllegalArgumentException("MatcherTree must have input");
}
if (proto.getInput().getTypedConfig().getTypeUrl()
.equals(TYPE_URL_HTTP_ATTRIBUTES_CEL_INPUT)) {
throw new IllegalArgumentException(
"HttpAttributesCelMatchInput cannot be used with MatcherTree");
}
if (proto.hasCustomMatch()) {
throw new IllegalArgumentException("MatcherTree does not support custom_match");
}
this.input = UnifiedMatcher.resolveInput(proto.getInput());
if (proto.hasExactMatchMap()) {
Matcher.MatcherTree.MatchMap matchMap = proto.getExactMatchMap();
if (matchMap.getMapCount() == 0) {
throw new IllegalArgumentException(
"MatcherTree exact_match_map must contain at least one entry");
}
this.exactMatchMap = new HashMap<>();
for (Map.Entry<String, Matcher.OnMatch> entry :
matchMap.getMapMap().entrySet()) {View on GitHub (pinned to 64daddc1f3)