grpc/grpc-go · error

failed to parse child policy config. This should never happe

Error message

failed to parse child policy config. This should never happen because the config was generated: %v

What it means

Returned by updateChildConfig (line 284) when b.childConfigParser.ParseConfig(childCfgBytes) fails on JSON that was just generated internally by buildPriorityConfigJSON. The message explicitly states 'This should never happen because the config was generated' — it is an internal invariant violation. The child config parser is the priority balancer's ParseConfig, and the input is JSON marshalled from a priority.LBConfig struct, so a parse failure indicates a structural mismatch between the generator and the parser.

Source

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

//
// A child policy is created if one doesn't already exist. The newly built
// configuration is then pushed to the child policy.
func (b *cdsBalancer) updateChildConfig() error {
	if b.childLB == nil {
		childLB, err := newChildBalancer(b.cc, b.bOpts)
		if err != nil {
			return fmt.Errorf("failed to create child policy of type %s: %v", priority.Name, err)
		}
		b.childLB = childLB
	}

	childCfgBytes, endpoints, err := buildPriorityConfigJSON(b.priorities, &b.xdsLBPolicy)
	if err != nil {
		return fmt.Errorf("failed to build child policy config: %v", err)
	}
	childCfg, err := b.childConfigParser.ParseConfig(childCfgBytes)
	if err != nil {
		return fmt.Errorf("failed to parse child policy config. This should never happen because the config was generated: %v", err)
	}
	if b.logger.V(2) {
		b.logger.Infof("Built child policy config: %s", pretty.ToJSON(childCfg))
	}

	for i := range endpoints {
		for j := range endpoints[i].Addresses {
			addr := endpoints[i].Addresses[j]
			addr.BalancerAttributes = endpoints[i].Attributes
			// BalancerAttributes are used for the following:
			// * Authority Override.
			// * grpc.lb.backend_service metric label propagation.
			// See https://github.com/grpc/grpc-go/issues/6472
			endpoints[i].Addresses[j] = addr
		}
	}
	if err := b.childLB.UpdateClientConnState(balancer.ClientConnState{
		ResolverState: resolver.State{

View on GitHub (pinned to 0c51461d27)

Solutions

  1. Run 'go mod tidy' and ensure all google.golang.org/grpc internal packages come from the exact same module version.
  2. Check 'go list -m all | grep grpc' for any replace directives or version mismatches.
  3. Report as a bug to grpc-go if versions are consistent — this is an internal invariant the maintainers need to fix.
  4. As a workaround, downgrade or upgrade to a known-good grpc-go release.
Defensive patterns

Strategy: try-catch

Try / catch

// Internal invariant violation — not catchable by user code.
// Report to grpc-go with full cluster resource and grpc-go version.
// Check module version consistency as a first step:
// go list -m all | grep 'google.golang.org/grpc'

Prevention

When it happens

Trigger: buildPriorityConfigJSON produces a priority.LBConfig, marshals it to JSON (line 101), and the priority balancer's ParseConfig (line 282) fails to unmarshal that same JSON. This can only happen if the priority.LBConfig struct and the priority balancer's expected JSON schema have diverged — a code-level inconsistency.

Common situations: Version skew where the cdsbalancer and priority packages are from different grpc-go versions. A code regression that changed the LBConfig struct fields without updating the priority parser (or vice versa). Mixing internal packages from different releases.

Understand the failure class

Related errors


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