{"record":{"id":"558b893153b8a198","repo":"grpc/grpc-go","slug":"unknown-header-matcher-type","errorCode":null,"errorMessage":"unknown header matcher type","messagePattern":"unknown header matcher type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/rbac/matchers.go","lineNumber":325,"sourceCode":"\t\tm = internalmatcher.NewHeaderRegexMatcher(headerMatcherConfig.Name, regex, headerMatcherConfig.InvertMatch)\n\tcase *v3route_componentspb.HeaderMatcher_RangeMatch:\n\t\tm = internalmatcher.NewHeaderRangeMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetRangeMatch().Start, headerMatcherConfig.GetRangeMatch().End, headerMatcherConfig.InvertMatch)\n\tcase *v3route_componentspb.HeaderMatcher_PresentMatch:\n\t\tm = internalmatcher.NewHeaderPresentMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetPresentMatch(), headerMatcherConfig.InvertMatch)\n\tcase *v3route_componentspb.HeaderMatcher_PrefixMatch:\n\t\tm = internalmatcher.NewHeaderPrefixMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetPrefixMatch(), headerMatcherConfig.InvertMatch)\n\tcase *v3route_componentspb.HeaderMatcher_SuffixMatch:\n\t\tm = internalmatcher.NewHeaderSuffixMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetSuffixMatch(), headerMatcherConfig.InvertMatch)\n\tcase *v3route_componentspb.HeaderMatcher_ContainsMatch:\n\t\tm = internalmatcher.NewHeaderContainsMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetContainsMatch(), headerMatcherConfig.InvertMatch)\n\tcase *v3route_componentspb.HeaderMatcher_StringMatch:\n\t\tsm, err := internalmatcher.StringMatcherFromProto(headerMatcherConfig.GetStringMatch())\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid string matcher %+v: %v\", headerMatcherConfig.GetStringMatch(), err)\n\t\t}\n\t\tm = internalmatcher.NewHeaderStringMatcher(headerMatcherConfig.Name, sm, headerMatcherConfig.InvertMatch)\n\tdefault:\n\t\treturn nil, errors.New(\"unknown header matcher type\")\n\t}\n\treturn &headerMatcher{matcher: m}, nil\n}\n\nfunc (hm *headerMatcher) match(data *rpcData) bool {\n\treturn hm.matcher.Match(data.md)\n}\n\n// urlPathMatcher matches on the URL Path of the incoming RPC. In gRPC, this\n// logically maps to the full method name the RPC is calling on the server side.\n// urlPathMatcher implements the matcher interface.\ntype urlPathMatcher struct {\n\tstringMatcher internalmatcher.StringMatcher\n}\n\nfunc newURLPathMatcher(pathMatcher *v3matcherpb.PathMatcher) (*urlPathMatcher, error) {\n\tstringMatcher, err := internalmatcher.StringMatcherFromProto(pathMatcher.GetPath())\n\tif err != nil {","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/rbac/matchers.go#L307-L343","documentation":"Returned by newHeaderMatcher (rbac/matchers.go:325) when the HeaderMatcher proto's HeaderMatchSpecifier oneof is set to a variant not handled by the type switch (exact, safe_regex, range, present, prefix, suffix, contains, string_match). The default branch covers any new Envoy header matcher type this gRPC build does not yet understand, failing loudly rather than silently ignoring the rule.","triggerScenarios":"An RBAC or route configuration uses a HeaderMatcher oneof variant introduced by a newer Envoy/xDS version than the gRPC client supports. The switch falls through to default and returns 'unknown header matcher type'.","commonSituations":"Control plane running a newer Envoy that emits a header matcher type (e.g. a new match variant) not implemented in this gRPC release; upgrading Envoy ahead of gRPC; custom envoy extensions adding matcher types.","solutions":["Upgrade the gRPC client to a version that supports the header matcher type in use.","Downgrade or reconfigure the control plane to emit only supported HeaderMatcher variants (exact/regex/range/present/prefix/suffix/contains/string).","Inspect the offending HeaderMatcher proto (log HeaderMatchSpecifier) to identify which variant is unsupported and adjust the policy."],"exampleFix":"// before: policy uses a header matcher variant gRPC does not know\n// after:  rewrite the RBAC rule using a supported matcher, e.g.\n//   header: { name: \"x-env\", exact_match: \"true\" }","handlingStrategy":"validation","validationCode":"// Before publishing an RBAC/route config, ensure every header matcher uses a\n// supported HeaderMatchSpecifier variant.\nvar supportedHeaderMatchers = map[reflect.Type]bool{\n    reflect.TypeOf(&v3route_componentspb.HeaderMatcher_ExactMatch{}): true,\n    reflect.TypeOf(&v3route_componentspb.HeaderMatcher_SafeRegexMatch{}): true,\n    reflect.TypeOf(&v3route_componentspb.HeaderMatcher_RangeMatch{}): true,\n    reflect.TypeOf(&v3route_componentspb.HeaderMatcher_PresentMatch{}): true,\n    reflect.TypeOf(&v3route_componentspb.HeaderMatcher_PrefixMatch{}): true,\n    reflect.TypeOf(&v3route_componentspb.HeaderMatcher_SuffixMatch{}): true,\n    reflect.TypeOf(&v3route_componentspb.HeaderMatcher_ContainsMatch{}): true,\n    reflect.TypeOf(&v3route_componentspb.HeaderMatcher_StringMatch{}): true,\n}\nfunc hmIsSupported(hm *v3route_componentspb.HeaderMatcher) bool {\n    return hm != nil && supportedHeaderMatchers[reflect.TypeOf(hm.HeaderMatchSpecifier)]\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep gRPC client and control-plane Envoy versions aligned to avoid new matcher types.","Lint header matchers against the supported set before publishing to gRPC.","Log the offending HeaderMatchSpecifier type when validation fails."],"tags":["xds","rbac","matcher","header","config","version"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}