grpc/grpc-go · error
rls: GrpcKeyBuilder in RouteLookupConfig has required_match
Error message
rls: GrpcKeyBuilder in RouteLookupConfig has required_match field set {%+v} What it means
Each header entry in a GrpcKeyBuilder has a required_match flag. The RLS key-builder semantics do not support conditional (required) header matching — all configured header keys are extracted unconditionally — so MakeBuilderMap rejects any header with required_match==true.
Source
Thrown at balancer/rls/internal/keys/builder.go:56
kbs := cfg.GetGrpcKeybuilders()
if len(kbs) == 0 {
return nil, errors.New("rls: RouteLookupConfig does not contain any GrpcKeyBuilder")
}
bm := make(map[string]builder)
for _, kb := range kbs {
// Extract keys from `headers`, `constant_keys` and `extra_keys` fields
// and populate appropriate values in the builder struct. Also ensure
// that keys are not repeated.
var matchers []matcher
seenKeys := make(map[string]bool)
constantKeys := kb.GetConstantKeys()
for k := range kb.GetConstantKeys() {
seenKeys[k] = true
}
for _, h := range kb.GetHeaders() {
if h.GetRequiredMatch() {
return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig has required_match field set {%+v}", kbs)
}
key := h.GetKey()
if seenKeys[key] {
return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q across headers, constant_keys and extra_keys {%+v}", key, kbs)
}
seenKeys[key] = true
matchers = append(matchers, matcher{key: h.GetKey(), names: h.GetNames()})
}
if seenKeys[kb.GetExtraKeys().GetHost()] {
return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers {%+v}", kb.GetExtraKeys().GetHost(), kbs)
}
if seenKeys[kb.GetExtraKeys().GetService()] {
return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers {%+v}", kb.GetExtraKeys().GetService(), kbs)
}
if seenKeys[kb.GetExtraKeys().GetMethod()] {
return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers {%+v}", kb.GetExtraKeys().GetMethod(), kbs)
}
b := builder{View on GitHub (pinned to 03255a9237)
Solutions
- Remove required_match (or set it false) from every header in every GrpcKeyBuilder.
- If you need presence-based routing, handle it upstream of RLS or use distinct key builders per path.
- Audit all grpc_keybuilders[].headers entries for the field.
Example fix
// before
"headers": [{ "key": "region", "names": ["x-region"], "required_match": true }]
// after
"headers": [{ "key": "region", "names": ["x-region"] }] Defensive patterns
Strategy: validation
Validate before calling
func validateNoRequiredMatch(cfg *rlspb.RouteLookupConfig) error {
for bi, kb := range cfg.GetGrpcKeybuilders() {
for hi, h := range kb.GetHeaders() {
if h.GetRequiredMatch() {
return fmt.Errorf("keybuilder[%d].header[%d] has required_match set", bi, hi)
}
}
}
return nil
} Prevention
- Do not reuse gRPC routing HeaderMatcher structs verbatim in RLS key builders.
- Audit every header entry for required_match before deploying.
- Strip required_match when converting routing rules to key builders.
When it happens
Trigger: A grpc_keybuilders[].headers[] entry with "required_match": true (proto HeaderMatcher.required_match). E.g. {"key":"region","names":["x-region"],"required_match":true}.
Common situations: Reusing HeaderMatcher structs from gRPC service config (where required_match is valid) inside an RLS key builder; translating routing rules verbatim into RLS key builders.
Related errors
- rls: GrpcKeyBuilder in RouteLookupConfig contains repeated k
- rls: GrpcKeyBuilder in RouteLookupConfig contains repeated k
- rls: GrpcKeyBuilder in RouteLookupConfig does not contain an
- rls: GrpcKeyBuilder in RouteLookupConfig contains a Name fie
- rls: GrpcKeyBuilder in RouteLookupConfig contains a method w
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/c4788f4aca43f45b.
Report an issue: GitHub.