grpc/grpc-go · error
%q LB policy is needed but not registered
Error message
%q LB policy is needed but not registered
What it means
Logged and wrapped in a nop balancer error in bb.Build() (line 72-73) when balancer.Get(priority.Name) returns nil at build time. This is a duplicate defensive check of error 341 but at the Build() entry point rather than the newChildBalancer factory. The balancer is placed into a nop (no-op) state with this error as its reason, causing the channel to report TRANSIENT_FAILURE.
Source
Thrown at internal/xds/balancer/cdsbalancer/cdsbalancer.go:73
)
func init() {
balancer.Register(bb{})
}
// bb implements the balancer.Builder interface to help build a cdsBalancer.
// It also implements the balancer.ConfigParser interface to help parse the
// JSON service config, to be passed to the cdsBalancer.
type bb struct{}
// Build creates a new CDS balancer with the ClientConn.
func (bb) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
builder := balancer.Get(priority.Name)
if builder == nil {
// Shouldn't happen, registered through imported Priority builder. Still,
// defensive programming.
logger.Errorf("%q LB policy is needed but not registered", priority.Name)
return nop.NewBalancer(cc, fmt.Errorf("%q LB policy is needed but not registered", priority.Name))
}
parser, ok := builder.(balancer.ConfigParser)
if !ok {
// Shouldn't happen, imported Priority builder has this method.
logger.Errorf("%q LB policy does not implement a config parser", priority.Name)
return nop.NewBalancer(cc, fmt.Errorf("%q LB policy does not implement a config parser", priority.Name))
}
b := &cdsBalancer{
bOpts: opts,
childConfigParser: parser,
clusterConfigs: make(map[string]*xdsresource.ClusterResult),
priorityConfigs: make(map[string]*priorityConfig),
cc: cc,
}
b.logger = prefixLogger(b)
b.logger.Infof("Created")
return bView on GitHub (pinned to 0c51461d27)
Solutions
- Import the full xds package so the priority balancer is registered: import _ "google.golang.org/grpc/xds".
- Check for version mismatches in go.mod: run 'go mod graph | grep grpc' and ensure no conflicting versions.
- If this appears in tests, ensure your test binary imports the priority package or uses grpc.NewClient with the xds resolver properly initialized.
Example fix
// before: partial import causing unregistered priority builder
import (
_ "google.golang.org/grpc/internal/xds/balancer/cdsbalancer"
)
// after: public xds import registers all dependent balancers
import (
_ "google.golang.org/grpc/xds"
) Defensive patterns
Strategy: validation
Validate before calling
// Startup check: verify required balancers are registered
func validateXDSBalancers() error {
required := []string{"cds_experimental", "priority_experimental"}
for _, name := range required {
if balancer.Get(name) == nil {
return fmt.Errorf("balancer %q not registered", name)
}
}
return nil
} Try / catch
// After channel creation, check connectivity state for TRANSIENT_FAILURE
state := conn.GetState()
if state == connectivity.TransientFailure {
// may indicate an unregistered balancer; check logs for the nop balancer error
} Prevention
- Use the public xds package import to ensure all balancers are registered.
- Add integration tests that create an xDS channel and verify it reaches READY.
- Check for balancer registration at startup to fail fast with a clear message.
When it happens
Trigger: The CDS balancer builder's Build() method is called by gRPC's balancer switching logic, and the priority balancer is not registered in the global registry. Identical root cause as error 341 but hit through a different code path — at initial balancer construction rather than during child balancer creation.
Common situations: Same as 341: missing priority package import, inconsistent grpc-go versions, or custom builds that strip the dependency. The comment at line 70-71 explicitly says 'Shouldn't happen, registered through imported Priority builder.'
Related errors
- xds: no balancer builder with name %v
- failed to create child policy of type %s: %v
- %q LB policy does not implement a config parser
- failed to push config to child policy: %v
- child policy %q not registered
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/45aa36ecef4a2a22.
Report an issue: GitHub.