grpc/grpc-go · error

rls: GrpcKeyBuilder in RouteLookupConfig contains repeated k

Error message

rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers {%+v}

What it means

extra_keys is a separate struct with host/service/method fields that name which RLS key the request's host should populate. After headers and constant_keys are seeded into seenKeys, MakeBuilderMap checks each extra_keys field for collision. This specific error is for the host field: extra_keys.host must not equal a key already used in constant_keys or headers.

Source

Thrown at balancer/rls/internal/keys/builder.go:66

		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{
			headerKeys:   matchers,
			constantKeys: constantKeys,
			hostKey:      kb.GetExtraKeys().GetHost(),
			serviceKey:   kb.GetExtraKeys().GetService(),
			methodKey:    kb.GetExtraKeys().GetMethod(),
		}

		// Store the builder created above in the BuilderMap based on the value
		// of the `Names` field, which wraps incoming request's service and
		// method. Also, ensure that there are no repeated `Names` field.

View on GitHub (pinned to 03255a9237)

Solutions

  1. Rename either the extra_keys.host value or the colliding constant/header key so they differ.
  2. Drop the redundant constant/header entry if the host key already conveys that value.
  3. Run a per-builder uniqueness check that includes host/service/method extra keys.

Example fix

// before
"constant_keys": {"host":"fixed"},
"extra_keys": {"host":"host"}
// after
"constant_keys": {"host":"fixed"},
"extra_keys": {"host":"client_host"}
Defensive patterns

Strategy: validation

Validate before calling

func validateExtraKeysUnique(kb *rlspb.GrpcKeyBuilder) error {
    seen := map[string]bool{}
    for k := range kb.GetConstantKeys() { seen[k] = true }
    for _, h := range kb.GetHeaders() { seen[h.GetKey()] = true }
    if h := kb.GetExtraKeys().GetHost(); h != "" && seen[h] {
        return fmt.Errorf("extra_keys.host %q duplicates a constant/header key", h)
    }
    return nil
}

Prevention

When it happens

Trigger: A GrpcKeyBuilder whose extra_keys.host equals a constant_keys key or a header key. E.g. constant_keys/headers use "host" and extra_keys.host is also "host".

Common situations: Naming the host-derived key "host" while a constant or header also uses "host"; copy-pasting extra_keys without checking overlap with headers.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/a08c3046c5ce30c0. Report an issue: GitHub.