{"record":{"id":"335396491bc1a4a3","repo":"grpc/grpc-java","slug":"matchertree-does-not-support-custom-match","errorCode":null,"errorMessage":"MatcherTree does not support custom_match","messagePattern":"MatcherTree does not support custom_match","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/internal/matcher/MatcherTree.java","lineNumber":52,"sourceCode":"  private final Map<String, OnMatch> exactMatchMap;\n  @Nullable \n  private final PrefixTrie prefixTrie;\n  @Nullable \n  private final OnMatch onNoMatch;\n  \n  MatcherTree(Matcher.MatcherTree proto, @Nullable Matcher.OnMatch onNoMatchProto,\n      Predicate<String> actionValidator) {\n    if (!proto.hasInput()) {\n      throw new IllegalArgumentException(\"MatcherTree must have input\");\n    }\n    if (proto.getInput().getTypedConfig().getTypeUrl()\n        .equals(TYPE_URL_HTTP_ATTRIBUTES_CEL_INPUT)) {\n      throw new IllegalArgumentException(\n          \"HttpAttributesCelMatchInput cannot be used with MatcherTree\");\n    }\n    \n    if (proto.hasCustomMatch()) {\n      throw new IllegalArgumentException(\"MatcherTree does not support custom_match\");\n    }\n    \n    this.input = UnifiedMatcher.resolveInput(proto.getInput());\n    \n    if (proto.hasExactMatchMap()) {\n      Matcher.MatcherTree.MatchMap matchMap = proto.getExactMatchMap();\n      if (matchMap.getMapCount() == 0) {\n        throw new IllegalArgumentException(\n            \"MatcherTree exact_match_map must contain at least one entry\");\n      }\n      this.exactMatchMap = new HashMap<>();\n      for (Map.Entry<String, Matcher.OnMatch> entry : \n          matchMap.getMapMap().entrySet()) {\n        this.exactMatchMap.put(entry.getKey(),\n            new OnMatch(entry.getValue(), actionValidator));\n      }\n      this.prefixTrie = null;\n    } else if (proto.hasPrefixMatchMap()) {","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/internal/matcher/MatcherTree.java#L34-L70","documentation":"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.","triggerScenarios":"Constructing MatcherTree from a proto where hasCustomMatch() is true (the custom_match oneof arm is set).","commonSituations":"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.","solutions":["Rewrite the tree using exact_match_map or prefix_match_map instead of custom_match.","Remove the custom_match field and choose a supported match strategy for the tree.","If a custom predicate is required, restructure as a MatcherList whose FieldMatcher uses custom_match."],"exampleFix":"// before\n{\"matcher_tree\": {\"input\": {...}, \"custom_match\": {\"typed_config\": {...}}}}\n// after\n{\"matcher_tree\": {\"input\": {...}, \"exact_match_map\": {\"map\": {\"key\": {\"matcher\": {...}}}}}}","handlingStrategy":"validation","validationCode":"if (treeProto.hasCustomMatch()) {\n  throw new IllegalArgumentException(\"custom_match trees unsupported; use exact_match_map or prefix_match_map\");\n}","typeGuard":"boolean usesSupportedTreeArm(Matcher.MatcherTree proto) {\n  return !proto.hasCustomMatch();\n}","tryCatchPattern":"try {\n  matcherTree = new MatcherTree(proto, onNoMatch, validator);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"custom_match\")) {\n    // translate custom_match into a supported map or list form\n  }\n  throw e;\n}","preventionTips":["Avoid custom_match in tree-form matcher configs","Check implementation support matrix before adopting new xDS fields","Convert custom predicates to exact/prefix maps where possible"],"tags":["xds","matcher","unsupported-field"],"backgroundTag":"unsupported-operation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}