grpc/grpc-go · critical

xds: no balancer builder with name %v

Error message

xds: no balancer builder with name %v

What it means

Returned by the newChildBalancer factory in cdsbalancer.go when balancer.Get(priority.Name) returns nil, meaning the priority LB policy builder is not in the global balancer registry. The CDS balancer depends on the priority balancer as its mandatory child; without it, no child balancer can be constructed and the error propagates up through updateChildConfig (line 273). The code comment says this is not expected to happen because the priority builder is registered via its package import side-effect.

Source

Thrown at internal/xds/balancer/cdsbalancer/cdsbalancer.go:49

	internalserviceconfig "google.golang.org/grpc/internal/serviceconfig"
	"google.golang.org/grpc/internal/xds/balancer/outlierdetection"
	"google.golang.org/grpc/internal/xds/balancer/priority"
	"google.golang.org/grpc/internal/xds/xdsclient"
	"google.golang.org/grpc/internal/xds/xdsclient/xdsresource"
	"google.golang.org/grpc/internal/xds/xdsdepmgr"
	"google.golang.org/grpc/resolver"
	"google.golang.org/grpc/serviceconfig"
)

const cdsName = "cds_experimental"

var (
	// newChildBalancer is a helper function to build a new priority balancer
	// and will be overridden in unittests.
	newChildBalancer = func(cc balancer.ClientConn, opts balancer.BuildOptions) (balancer.Balancer, error) {
		builder := balancer.Get(priority.Name)
		if builder == nil {
			return nil, fmt.Errorf("xds: no balancer builder with name %v", priority.Name)
		}
		// We directly pass the parent clientConn to the underlying priority
		// balancer because the cdsBalancer does not deal with subConns.
		return builder.Build(cc, opts), nil
	}
)

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 {

View on GitHub (pinned to 0c51461d27)

Solutions

  1. Ensure the priority balancer package is imported (blank import if needed): import _ "google.golang.org/grpc/internal/xds/balancer/priority".
  2. Prefer using the top-level xds package (google.golang.org/grpc/xds) which transitively imports the full balancer chain, rather than importing internal sub-packages directly.
  3. Verify you are on a consistent single version of grpc-go across all modules; run 'go mod tidy' and check 'go list -m google.golang.org/grpc' has no 'replace' mismatch.
  4. In test code, if newChildBalancer is overridden, confirm the override does not bypass the real registration check.

Example fix

// before: only cdsbalancer imported, priority missing
import _ "google.golang.org/grpc/internal/xds/balancer/cdsbalancer"

// after: use the public xds package which imports the full chain
import _ "google.golang.org/grpc/xds"
Defensive patterns

Strategy: validation

Validate before calling

// Verify the priority balancer is registered before using xDS
func validateBalancerRegistered(name string) bool {
    return balancer.Get(name) != nil
}

// Call during init after importing xds:
func init() {
    if !validateBalancerRegistered("priority_experimental") {
        log.Fatal("priority balancer not registered — ensure xds package is imported")
    }
}

Try / catch

// Check the error from grpc.NewClient or from xDS resolver operations
conn, err := xds.NewClientCredentials(...) // or grpc.Dial with xds
if err != nil {
    if strings.Contains(err.Error(), "no balancer builder") {
        log.Fatal("Required balancer not registered. Add: import _ \"google.golang.org/grpc/xds\"")
    }
}

Prevention

When it happens

Trigger: The cds_experimental balancer is invoked (via xDS-driven service config) but the priority balancer package was never imported, so its init()-based registration never ran. This can happen in a custom build that selectively imports only parts of the xDS balancer tree, or in test setups that construct the CDS balancer without importing the full dependency chain.

Common situations: A developer building a minimal gRPC xDS client imports only the cdsbalancer package (or it gets pulled in transitively) without importing google.golang.org/grpc/internal/xds/balancer/priority. Binary stripping or dead-code elimination removing the side-effect import. Mixing versions of grpc-go where the priority package path or name constant changed.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/7b839d4494b631f4. Report an issue: GitHub.