{"record":{"id":"e590763c5bae7dc5","repo":"grpc/grpc-java","slug":"unknown-header-matcher-type","errorCode":null,"errorMessage":"Unknown header matcher type: ","messagePattern":"Unknown header matcher type: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/internal/MatcherParser.java","lineNumber":85,"sourceCode":"        String prefixMatch = proto.getPrefixMatch();\n        return Matchers.HeaderMatcher.forPrefix(\n              proto.getName(), prefixMatch, proto.getInvertMatch());\n      case SUFFIX_MATCH:\n        @SuppressWarnings(\"deprecation\") // gRFC A63: support indefinitely\n        String suffixMatch = proto.getSuffixMatch();\n        return Matchers.HeaderMatcher.forSuffix(\n              proto.getName(), suffixMatch, proto.getInvertMatch());\n      case CONTAINS_MATCH:\n        @SuppressWarnings(\"deprecation\") // gRFC A63: support indefinitely\n        String containsMatch = proto.getContainsMatch();\n        return Matchers.HeaderMatcher.forContains(\n              proto.getName(), containsMatch, proto.getInvertMatch());\n      case STRING_MATCH:\n        return Matchers.HeaderMatcher.forString(\n          proto.getName(), parseStringMatcher(proto.getStringMatch()), proto.getInvertMatch());\n      case HEADERMATCHSPECIFIER_NOT_SET:\n      default:\n        throw new IllegalArgumentException(\n                \"Unknown header matcher type: \" + proto.getHeaderMatchSpecifierCase());\n    }\n  }\n\n  /** Translate StringMatcher envoy proto to internal StringMatcher. */\n  public static Matchers.StringMatcher parseStringMatcher(\n            io.envoyproxy.envoy.type.matcher.v3.StringMatcher proto) {\n    switch (proto.getMatchPatternCase()) {\n      case EXACT:\n        return Matchers.StringMatcher.forExact(proto.getExact(), proto.getIgnoreCase());\n      case PREFIX:\n        return Matchers.StringMatcher.forPrefix(proto.getPrefix(), proto.getIgnoreCase());\n      case SUFFIX:\n        return Matchers.StringMatcher.forSuffix(proto.getSuffix(), proto.getIgnoreCase());\n      case SAFE_REGEX:\n        return Matchers.StringMatcher.forSafeRegEx(\n                Pattern.compile(proto.getSafeRegex().getRegex()));\n      case CONTAINS:","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/internal/MatcherParser.java#L67-L103","documentation":"parseHeaderMatcher switches over the HeaderMatchSpecifierCase of the Envoy HeaderMatcher proto. When the specifier is HEADERMATCHSPECIFIER_NOT_SET (or any unrecognized case) the matcher type cannot be determined, so an IllegalArgumentException naming the case is thrown. It means the header match in the xDS config has no (or an unknown) match type.","triggerScenarios":"An Envoy HeaderMatcher proto arrives with no specifier set (present_match/exact_match/regex_match etc. all absent) or uses a specifier case this parser version does not know.","commonSituations":"Control plane emits a header match with only 'invert_match' or an empty matcher; older client receiving newer Envoy API specifier cases (e.g. present_match) it doesn't support; malformed config generation dropping the match field.","solutions":["Fix the xDS config so each header_match sets exactly one specifier (exact_match, safe_regex_match, range_match, present_match, or string_match)","Upgrade grpc-xds to a version that recognizes the specifier case in use","Log the reported HeaderMatchSpecifierCase to identify which field is missing","Validate management-server output against the Envoy API version your client supports"],"exampleFix":"// before: header match with no specifier\n{\"name\":\"x-flag\",\"invert_match\":true}\n// after\n{\"name\":\"x-flag\",\"string_match\":{\"exact\":\"true\"},\"invert_match\":true}","handlingStrategy":"validation","validationCode":"if (proto.getHeaderMatchSpecifierCase() == HeaderMatchSpecifierCase.HEADERMATCHSPECIFIER_NOT_SET) { reject(\"header match has no specifier\"); }","typeGuard":"null","tryCatchPattern":"try { matcher = MatcherParser.parseHeaderMatcher(proto); }\ncatch (IllegalArgumentException e) { log.error(\"Unsupported header match type: \" + e.getMessage()); skipOrReject(); }","preventionTips":["Always set exactly one specifier per header_match","Keep grpc-xds updated with your Envoy API version","Validate config server-side before distribution"],"tags":["xds","config","validation","envoy"],"backgroundTag":"invalid-enum-value","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"}