grpc/grpc-go · error

RLS LB policy not registered

Error message

RLS LB policy not registered

What it means

Returned by ParseClusterSpecifierConfig when balancer.Get(internal.RLSLoadBalancingPolicyName) returns nil, meaning the RLS load balancer policy was never registered with the gRPC balancer registry. Without it, the cluster specifier cannot validate or build the child policy, so the config is rejected.

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

Solutions

  1. Add a blank import of the RLS balancer package in your main package (e.g. _ "google.golang.org/grpc/balancer/rls").
  2. Verify the import is not dead-code-eliminated (call balancer.Get at startup to confirm registration).
  3. Check gRPC version: the RLS balancer name constant must match internal.RLSLoadBalancingPolicyName in your grpc-go version.

Example fix

// before: only the cluster specifier is imported
import _ "google.golang.org/grpc/internal/xds/clusterspecifier/rls"

// after: also register the RLS balancer
import (
  _ "google.golang.org/grpc/balancer/rls"
  _ "google.golang.org/grpc/internal/xds/clusterspecifier/rls"
)
Defensive patterns

Strategy: validation

Validate before calling

// At startup, confirm the RLS balancer is registered.
func ensureRLSBalancerRegistered() error {
    if balancer.Get(internal.RLSLoadBalancingPolicyName) == nil {
        return errors.New("RLS balancer not registered; blank-import the rls balancer package")
    }
    return nil
}

Prevention

When it happens

Trigger: The binary imports the RLS cluster specifier plugin but does not import/register the RLS balancer package (blank import of the rls balancer). The plugin's init() registers itself, but the balancer it depends on is registered separately.

Common situations: A custom binary or test that pulls in xds/clusterspecifier/rls without the corresponding balancer/rls package, or a build that uses build tags/linker flags that drop the RLS balancer registration.

Related errors


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