grpc/grpc-go · error

unexpected balancer config with type: %T

Error message

unexpected balancer config with type: %T

What it means

The cluster_impl balancer's UpdateClientConnState expects BalancerConfig to be of type *LBConfig (the cluster_impl-specific config struct). This error fires when the config has a different type, indicating a misconfiguration in how the balancer tree was assembled. The config should always be *LBConfig when the CDS/priority balancer properly routes to cluster_impl.

Source

Thrown at internal/xds/balancer/clusterimpl/clusterimpl.go:404

	oldHI := b.xdsHIPtr.Swap(newHI)
	if oldHI != nil {
		oldHI.Decrement()
	}
	return nil
}

func (b *clusterImplBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
	defer clientConnUpdateHook()

	b.mu.Lock()
	b.inhibitPickerUpdates = true
	b.mu.Unlock()
	if b.logger.V(2) {
		b.logger.Infof("Received configuration: %s", pretty.ToJSON(s.BalancerConfig))
	}
	newConfig, ok := s.BalancerConfig.(*LBConfig)
	if !ok {
		return fmt.Errorf("unexpected balancer config with type: %T", s.BalancerConfig)
	}

	// Need to check for potential errors at the beginning of this function, so
	// that on errors, we reject the whole config, instead of applying part of
	// it.
	bb := balancer.Get(newConfig.ChildPolicy.Name)
	if bb == nil {
		return fmt.Errorf("child policy %q not registered", newConfig.ChildPolicy.Name)
	}

	if b.xdsClient == nil {
		c := xdsclient.FromResolverState(s.ResolverState)
		if c == nil {
			return balancer.ErrBadResolverState
		}
		b.xdsClient = c
	}

View on GitHub (pinned to 03255a9237)

Solutions

  1. This error indicates an internal gRPC configuration error — the balancer tree assembly is broken. Report as a bug with the grpc-go version and xDS configuration
  2. Verify you are not manually constructing balancer configs for the xDS balancer chain
  3. Ensure no custom balancer intercepts or replaces the config passed to cluster_impl
  4. Upgrade grpc-go to a stable release, as this may be a regression
  5. Enable GRPC_GO_LOG_SEVERITY=info to see what config type was actually received
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify the config type matches before calling UpdateClientConnState
// (applicable if constructing balancer configs programmatically)
func isClusterImplConfig(cfg serviceconfig.LoadBalancingConfig) bool {
    _, ok := cfg.(*clusterimpl.LBConfig)
    return ok
}

Type guard

// Type guard for cluster_impl config
func isClusterImplLBConfig(v interface{}) bool {
    _, ok := v.(*clusterimpl.LBConfig)
    return ok
}

Prevention

When it happens

Trigger: Triggered at the start of cluster_impl's UpdateClientConnState when the type assertion s.BalancerConfig.(*LBConfig) fails. This means the resolver or parent balancer passed a config of an unexpected type (e.g., a raw map, a different balancer's config struct, or nil).

Common situations: A misconfigured xDS balancer chain where the wrong config type is routed to cluster_impl; a bug in the parent priority or CDS balancer that constructs the wrong config type; manual or programmatic construction of balancer.ClientConnState with incorrect config types; a version mismatch where LBConfig struct layout changed between packages.

Related errors


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