grpc/grpc-go · error

rls: GrpcKeyBuilder in RouteLookupConfig contains a Name…

Error message

rls: GrpcKeyBuilder in RouteLookupConfig contains a Name field with no Service {%+v}

What it means

Inside a GrpcKeyBuilder, each Name must carry a non-empty Service because the service component is what the builder map is keyed against (builder.go:89-91). A Name with only a Method and no Service is ambiguous: it cannot be turned into a "/service/method" or "/service/" path. grpc-go rejects it rather than guessing.

Solutions

  1. Set Name.Service to the fully-qualified gRPC service name (e.g., "my.pkg.Greeter") for every Name entry.
  2. Leave Method empty if you want the builder to match every method on that service.

Example fix

// before
kb.Names = []*rlspb.Name{{Method: "SayHello"}} // Service empty
// after
kb.Names = []*rlspb.Name{{Service: "my.pkg.Greeter", Method: "SayHello"}}
Defensive patterns

Strategy: validation

Validate before calling

func validateNamesHaveService(cfg *rlspb.RouteLookupConfig) error {
	for _, kb := range cfg.GetGrpcKeybuilders() {
		for _, n := range kb.GetNames() {
			if n.GetService() == "" {
				return fmt.Errorf("GrpcKeyBuilder Name missing Service")
			}
		}
	}
	return nil
}

Prevention

When it happens

Trigger: A GrpcKeyBuilder.Name with Method="Do" but Service="" (or Service omitted). Caught at builder.go:90 where name.GetService() returns "".

Common situations: Building Name protos programmatically and forgetting to populate Service; truncating a config; assuming Method alone is enough.

Related errors


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

Appendix: source

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

		}
		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
}

// KeyMap represents the RLS keys to be used for a request.
type KeyMap struct {
	// Map is the representation of an RLS key as a Go map. This is used when
	// an actual RLS request is to be sent out on the wire, since the

View on GitHub (pinned to 0c51461d27)