grpc/grpc-java · error · IllegalArgumentException

MatcherTree does not support custom_match

Error message

MatcherTree does not support custom_match

What it means

MatcherTree only supports the built-in exact_match_map and prefix_match_map key-matching strategies; a custom_match tree matcher is not implemented by this library, so the constructor throws. This surfaces the unsupported xDS field early rather than failing at match time.

Solutions

  1. Rewrite the tree using exact_match_map or prefix_match_map instead of custom_match.
  2. Remove the custom_match field and choose a supported match strategy for the tree.
  3. If a custom predicate is required, restructure as a MatcherList whose FieldMatcher uses custom_match.

Example fix

// before
{"matcher_tree": {"input": {...}, "custom_match": {"typed_config": {...}}}}
// after
{"matcher_tree": {"input": {...}, "exact_match_map": {"map": {"key": {"matcher": {...}}}}}}
Defensive patterns

Strategy: validation

Validate before calling

if (treeProto.hasCustomMatch()) {
  throw new IllegalArgumentException("custom_match trees unsupported; use exact_match_map or prefix_match_map");
}

Type guard

boolean usesSupportedTreeArm(Matcher.MatcherTree proto) {
  return !proto.hasCustomMatch();
}

Try / catch

try {
  matcherTree = new MatcherTree(proto, onNoMatch, validator);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("custom_match")) {
    // translate custom_match into a supported map or list form
  }
  throw e;
}

Prevention

When it happens

Trigger: Constructing MatcherTree from a proto where hasCustomMatch() is true (the custom_match oneof arm is set).

Common situations: Envoy configs that use a custom match extension for tree matching ported to this gRPC xDS matcher implementation, which does not yet support custom_match.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/MatcherTree.java:52

  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()) {
        this.exactMatchMap.put(entry.getKey(),
            new OnMatch(entry.getValue(), actionValidator));
      }
      this.prefixTrie = null;
    } else if (proto.hasPrefixMatchMap()) {

View on GitHub (pinned to 64daddc1f3)