grpc/grpc-go · error
unknown header matcher type
Error message
unknown header matcher type
What it means
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.
Source
Thrown at internal/xds/rbac/matchers.go:325
m = internalmatcher.NewHeaderRegexMatcher(headerMatcherConfig.Name, regex, headerMatcherConfig.InvertMatch)
case *v3route_componentspb.HeaderMatcher_RangeMatch:
m = internalmatcher.NewHeaderRangeMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetRangeMatch().Start, headerMatcherConfig.GetRangeMatch().End, headerMatcherConfig.InvertMatch)
case *v3route_componentspb.HeaderMatcher_PresentMatch:
m = internalmatcher.NewHeaderPresentMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetPresentMatch(), headerMatcherConfig.InvertMatch)
case *v3route_componentspb.HeaderMatcher_PrefixMatch:
m = internalmatcher.NewHeaderPrefixMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetPrefixMatch(), headerMatcherConfig.InvertMatch)
case *v3route_componentspb.HeaderMatcher_SuffixMatch:
m = internalmatcher.NewHeaderSuffixMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetSuffixMatch(), headerMatcherConfig.InvertMatch)
case *v3route_componentspb.HeaderMatcher_ContainsMatch:
m = internalmatcher.NewHeaderContainsMatcher(headerMatcherConfig.Name, headerMatcherConfig.GetContainsMatch(), headerMatcherConfig.InvertMatch)
case *v3route_componentspb.HeaderMatcher_StringMatch:
sm, err := internalmatcher.StringMatcherFromProto(headerMatcherConfig.GetStringMatch())
if err != nil {
return nil, fmt.Errorf("invalid string matcher %+v: %v", headerMatcherConfig.GetStringMatch(), err)
}
m = internalmatcher.NewHeaderStringMatcher(headerMatcherConfig.Name, sm, headerMatcherConfig.InvertMatch)
default:
return nil, errors.New("unknown header matcher type")
}
return &headerMatcher{matcher: m}, nil
}
func (hm *headerMatcher) match(data *rpcData) bool {
return hm.matcher.Match(data.md)
}
// urlPathMatcher matches on the URL Path of the incoming RPC. In gRPC, this
// logically maps to the full method name the RPC is calling on the server side.
// urlPathMatcher implements the matcher interface.
type urlPathMatcher struct {
stringMatcher internalmatcher.StringMatcher
}
func newURLPathMatcher(pathMatcher *v3matcherpb.PathMatcher) (*urlPathMatcher, error) {
stringMatcher, err := internalmatcher.StringMatcherFromProto(pathMatcher.GetPath())
if err != nil {View on GitHub (pinned to 03255a9237)
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.
Example fix
// before: policy uses a header matcher variant gRPC does not know
// after: rewrite the RBAC rule using a supported matcher, e.g.
// header: { name: "x-env", exact_match: "true" } Defensive patterns
Strategy: validation
Validate before calling
// Before publishing an RBAC/route config, ensure every header matcher uses a
// supported HeaderMatchSpecifier variant.
var supportedHeaderMatchers = map[reflect.Type]bool{
reflect.TypeOf(&v3route_componentspb.HeaderMatcher_ExactMatch{}): true,
reflect.TypeOf(&v3route_componentspb.HeaderMatcher_SafeRegexMatch{}): true,
reflect.TypeOf(&v3route_componentspb.HeaderMatcher_RangeMatch{}): true,
reflect.TypeOf(&v3route_componentspb.HeaderMatcher_PresentMatch{}): true,
reflect.TypeOf(&v3route_componentspb.HeaderMatcher_PrefixMatch{}): true,
reflect.TypeOf(&v3route_componentspb.HeaderMatcher_SuffixMatch{}): true,
reflect.TypeOf(&v3route_componentspb.HeaderMatcher_ContainsMatch{}): true,
reflect.TypeOf(&v3route_componentspb.HeaderMatcher_StringMatch{}): true,
}
func hmIsSupported(hm *v3route_componentspb.HeaderMatcher) bool {
return hm != nil && supportedHeaderMatchers[reflect.TypeOf(hm.HeaderMatchSpecifier)]
} Prevention
- 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.
When it happens
Trigger: 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'.
Common situations: 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.
Related errors
- input StringMatcher proto is nil
- empty prefix is not allowed in StringMatcher
- empty suffix is not allowed in StringMatcher
- empty contains is not allowed in StringMatcher
- rbac: Policy.condition is present
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/558b893153b8a198.
Report an issue: GitHub.