grpc/grpc-go · error

rls: GrpcKeyBuilder in RouteLookupConfig does not contain…

Error message

rls: GrpcKeyBuilder in RouteLookupConfig does not contain any Name {%+v}

What it means

Each GrpcKeyBuilder must declare at least one Name (a service/method or service-wide binding) so the RLS LB knows which request paths the builder applies to (builder.go:85-87). A GrpcKeyBuilder with headers/constant_keys but no Names has no routing scope and is rejected, because BuilderMap would have nowhere to register it.

Solutions

  1. Add at least one Name with a non-empty Service (Method may be empty for service-wide matching) to the offending GrpcKeyBuilder.
  2. If the builder is vestigial, remove it from grpc_keybuilders entirely.

Example fix

// before
kb := &rlspb.GrpcKeyBuilder{
  ConstantKeys: map[string]string{"region": "us"},
  // Names missing
}
// after
kb := &rlspb.GrpcKeyBuilder{
  ConstantKeys: map[string]string{"region": "us"},
  Names:         []*rlspb.GrpcKeyBuilder_Name{{Service: "my.pkg.Svc", Method: "Do"}},
}
Defensive patterns

Strategy: validation

Validate before calling

func validateNamesPresent(cfg *rlspb.RouteLookupConfig) error {
	for i, kb := range cfg.GetGrpcKeybuilders() {
		if len(kb.GetNames()) == 0 {
			return fmt.Errorf("grpc_keybuilders[%d] has no Name", i)
		}
	}
	return nil
}

Prevention

When it happens

Trigger: A GrpcKeyBuilder inside RouteLookupConfig.grpc_keybuilders has an empty Names slice. The check `len(names) == 0` at builder.go:86 returns this error.

Common situations: Partially constructed key builder protos; a config editor that adds header matchers but forgets the Name binding; an xDS config push missing the names field.

Related errors


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

Appendix: source

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

			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.
		names := kb.GetNames()
		if len(names) == 0 {
			return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig does not contain any Name {%+v}", kbs)
		}
		for _, name := range names {
			if name.GetService() == "" {
				return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains a Name field with no Service {%+v}", kbs)
			}
			if strings.Contains(name.GetMethod(), `/`) {
				return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains a method with a slash {%+v}", kbs)
			}
			path := "/" + name.GetService() + "/" + name.GetMethod()
			if _, ok := bm[path]; ok {
				return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains repeated Name field {%+v}", kbs)
			}
			bm[path] = b
		}
	}
	return bm, nil
}

View on GitHub (pinned to 0c51461d27)