grpc/grpc-go · error
RLS LB policy not registered
Error message
RLS LB policy not registered
What it means
The RLS load balancer policy named 'rls_experimental' is not found in the gRPC balancer registry (rls.go:86-88). The cluster specifier plugin calls balancer.Get to locate the RLS LB policy for config validation, and a nil return means no balancer with that name has registered itself via init().
Solutions
- Add a blank import of the RLS balancer: import _ "google.golang.org/grpc/balancer/rls"
- Verify the import appears before any xDS resource processing occurs
- Check that build tags or build constraints are not excluding the balancer/rls package
- Confirm the gRPC version includes the RLS balancer (available since gRPC 1.40+)
Example fix
// before — RLS cluster specifier imported but not the RLS balancer
import (
_ "google.golang.org/grpc/internal/xds/clusterspecifier/rls"
)
// after — also import the RLS balancer to register it
import (
_ "google.golang.org/grpc/balancer/rls"
_ "google.golang.org/grpc/internal/xds/clusterspecifier/rls"
) Defensive patterns
Strategy: validation
Validate before calling
// Verify the RLS LB policy is registered at startup.
if balancer.Get(internal.RLSLoadBalancingPolicyName) == nil {
log.Fatal("RLS LB policy not registered — add: import _ \"google.golang.org/grpc/balancer/rls\"")
} Prevention
- Always import both the RLS cluster specifier plugin and the RLS balancer package together
- Add a startup assertion that checks critical balancer registrations
- Review import lists when adding xDS RLS support to ensure all dependencies are included
- Use a centralized import file for xDS-related blank imports
When it happens
Trigger: balancer.Get(internal.RLSLoadBalancingPolicyName) returns nil because the RLS balancer package (google.golang.org/grpc/balancer/rls) was never imported, so its init() function that calls balancer.Register never executed.
Common situations: Application imports the RLS cluster specifier plugin but not the RLS balancer package; using a stripped-down or custom gRPC build that excludes the RLS balancer; build tags or constraints stripping the balancer/rls package; init ordering issue.
Related errors
- xds: no balancer builder with name
- child policy not registered
- failed to create child policy of type
- outlier detection: child balancer
- LB policy is needed but not registered
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/c924555ac819058d.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/clusterspecifier/rls/rls.go:88
}
lbCfgJSON := &lbConfigJSON{
RouteLookupConfig: rlcJSON, // "JSON form of RouteLookupClusterSpecifier.config" - RLS in xDS Design Doc
ChildPolicy: []map[string]json.RawMessage{
{
"cds_experimental": json.RawMessage(`{"isDynamic":true}`),
},
},
ChildPolicyConfigTargetFieldName: "cluster",
}
rawJSON, err := json.Marshal(lbCfgJSON)
if err != nil {
return nil, fmt.Errorf("rls_csp: error marshaling load balancing config %v: %v", lbCfgJSON, err)
}
rlsBB := balancer.Get(internal.RLSLoadBalancingPolicyName)
if rlsBB == nil {
return nil, fmt.Errorf("RLS LB policy not registered")
}
if _, err = rlsBB.(balancer.ConfigParser).ParseConfig(rawJSON); err != nil {
return nil, fmt.Errorf("rls_csp: validation error from rls lb policy parsing: %v", err)
}
return clusterspecifier.BalancerConfig{{internal.RLSLoadBalancingPolicyName: lbCfgJSON}}, nil
}
View on GitHub (pinned to 0c51461d27)