grpc/grpc-go · error

rls: GrpcKeyBuilder in RouteLookupConfig contains a Name fie

Error message

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

What it means

Each Name in a GrpcKeyBuilder is a {service, method} pair where the library splits the request path as /service/method. An empty service makes the path malformed, so MakeBuilderMap requires name.GetService() != "" and rejects any Name lacking a service.

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 03255a9237)

Solutions

  1. Set service to the fully-qualified gRPC service name (e.g. "pkg.Svc").
  2. For a catch-all across a service, set method to "" (empty) while keeping service set.
  3. Lint every Name to ensure service is non-empty.

Example fix

// before
{"names":[{"method":"Get"}]}
// after
{"names":[{"service":"pkg.Svc","method":"Get"}]}
Defensive patterns

Strategy: validation

Validate before calling

func validateNameService(cfg *rlspb.RouteLookupConfig) error {
    for bi, kb := range cfg.GetGrpcKeybuilders() {
        for ni, n := range kb.GetNames() {
            if n.GetService() == "" {
                return fmt.Errorf("keybuilder[%d].names[%d] missing service", bi, ni)
            }
        }
    }
    return nil
}

Prevention

When it happens

Trigger: A names entry like {"method":"DoThing"} with no service, or {"service":"","method":"DoThing"}.

Common situations: Building Name protos programmatically and forgetting to set Service; confusing the fully-qualified path (which is split later) with the service field; bad xDS data.

Related errors


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