grpc/grpc-go · error

rls: GrpcKeyBuilder in RouteLookupConfig contains repeated…

Error message

rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q across headers, constant_keys and extra_keys {%+v}

What it means

When building the RLS key map, grpc-go collects every key name from constant_keys, headers, and extra_keys into a single set and forbids duplicates (builder.go:49-63). If a header's key string equals a key already present in constant_keys (or another header), MakeBuilderMap returns this error. Each RLS key field must map to a uniquely named key in the outgoing RouteLookupRequest.

Solutions

  1. Inspect the reported duplicate key name and search the GrpcKeyBuilder's constant_keys, headers, and extra_keys for all occurrences.
  2. Rename one of the colliding entries so every key name is unique within a single GrpcKeyBuilder.
  3. If the duplication is intentional (two sources feeding one key), collapse them into a single header matcher with multiple Names.

Example fix

// before
kb := &rlspb.GrpcKeyBuilder{
  ConstantKeys: map[string]string{"region": "us"},
  Headers:      []*rlspb.Header{{Key: "region", Names: []string{"x-region"}}},
}
// after
kb := &rlspb.GrpcKeyBuilder{
  ConstantKeys: map[string]string{"region": "us"},
  Headers:      []*rlspb.Header{{Key: "zone", Names: []string{"x-zone"}}}, // renamed
}
Defensive patterns

Strategy: validation

Validate before calling

func validateUniqueKeys(cfg *rlspb.RouteLookupConfig) error {
	for _, kb := range cfg.GetGrpcKeybuilders() {
		seen := map[string]bool{}
		for k := range kb.GetConstantKeys() {
			if seen[k] { return fmt.Errorf("dup constant key %q", k) }
			seen[k] = true
		}
		for _, h := range kb.GetHeaders() {
			k := h.GetKey()
			if seen[k] { return fmt.Errorf("repeated key %q across constant/headers", k) }
			seen[k] = true
		}
	}
	return nil
}

Prevention

When it happens

Trigger: A GrpcKeyBuilder declares a constant_keys entry with key "zone" and also a header with key "zone"; or two headers share the same key. The seenKeys map (seeded from constant_keys, then from each header) detects the collision at builder.go:59.

Common situations: Renaming a key in one place but not the other when editing an RLS config; merging two key builders together; an xDS-sourced config where constant_keys and header keys were authored independently.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/83e766f77d402a64. Report an issue: GitHub.

Appendix: source

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

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

View on GitHub (pinned to 0c51461d27)