grpc/grpc-go · error

rls: GrpcKeyBuilder in RouteLookupConfig does not contain an

Error message

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

What it means

A GrpcKeyBuilder maps a set of service/method Names to a key-building rule; without any Name it can never match an incoming RPC. MakeBuilderMap requires len(kb.GetNames()) > 0 and rejects a builder with an empty Names list.

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

Solutions

  1. Add at least one Name {service, method} to the builder; for whole-service matching use method "" (empty).
  2. If the builder is not needed, remove it from grpc_keybuilders.
  3. Validate that every builder has len(names) >= 1 before deploying.

Example fix

// before
{"headers":[{"key":"k","names":["x-k"]}]}
// after
{"names":[{"service":"pkg.Svc","method":""}],
 "headers":[{"key":"k","names":["x-k"]}]}
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("keybuilder[%d] has no Name", i)
        }
    }
    return nil
}

Prevention

When it happens

Trigger: A grpc_keybuilders entry with no "names" field, or names: []. The key builder has headers/constant_keys defined but nothing it applies to.

Common situations: Building key builders from a loop and forgetting to set Names; a default/template builder left without a Name; malformed xDS conversion dropping the Names field.

Related errors


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