vitessio/vitess · error
failed to initialize service config with load balancer polic
Error message
failed to initialize service config with load balancer policy %s: %s
What it means
During resolver build, if a BalancerPolicy is configured, the builder constructs a gRPC service config JSON ({"loadBalancingConfig": [{policy: {}}]}) and asks the ClientConn to parse it. If ParseServiceConfig fails (unknown/unregistered LB policy name or malformed config), this error wraps the parse error with the policy that caused it.
Source
Thrown at go/vt/vtadmin/cluster/resolver/resolver.go:265
}
func (b *builder) build(target grpcresolver.Target, cc grpcresolver.ClientConn, opts grpcresolver.BuildOptions) (*resolver, error) {
var fn func(context.Context, []string) ([]string, error)
switch target.URL.Host {
case "vtctld":
fn = b.opts.Discovery.DiscoverVtctldAddrs
case "vtgate":
fn = b.opts.Discovery.DiscoverVTGateAddrs
default:
return nil, fmt.Errorf("%s: unsupported URL host %s", logPrefix, target.URL.Host)
}
var sc serviceconfig.Config
if b.opts.BalancerPolicy != "" {
// c.f. https://github.com/grpc/grpc/blob/master/doc/service_config.md#example
scpr := cc.ParseServiceConfig(fmt.Sprintf(`{"loadBalancingConfig": [{ "%s": {} }] }`, b.opts.BalancerPolicy))
if scpr.Err != nil {
return nil, fmt.Errorf("failed to initialize service config with load balancer policy %s: %s", b.opts.BalancerPolicy, scpr.Err)
}
sc = scpr.Config
}
ctx, cancel := context.WithCancel(context.Background())
r := &resolver{
component: target.URL.Host,
// use the original cluster ID (not the sanitized scheme) for debugging/logging
cluster: b.clusterID,
discoverAddrs: fn,
backoffStrategy: backoff.Get(b.opts.BackoffStrategy, b.opts.BackoffConfig),
opts: b.opts,
cc: cc,
sc: sc,
rn: make(chan struct{}, 1),
ctx: ctx,View on GitHub (pinned to 01a25a7d17)
Solutions
- Confirm the policy string matches the gRPC-registered balancer name ('pickfirst', 'round_robin').
- Cross-check with BalancerPolicy.Set validation — use a value accepted there.
- Read the wrapped %s (scpr.Err) for gRPC's own explanation.
- Remove BalancerPolicy so the default service config is used.
Example fix
// before opts.BalancerPolicy = "pick_first" // after opts.BalancerPolicy = "pickfirst"
Defensive patterns
Strategy: validation
Validate before calling
if policy != "" {
sc := fmt.Sprintf(`{"loadBalancingConfig": [{ %q: {} }]}`, policy)
if _, err := json.Marshal(json.RawMessage(sc)); err != nil {
return fmt.Errorf("invalid service config: %w", err)
}
bp := resolver.BalancerPolicy("")
if err := bp.Set(policy); err != nil {
return fmt.Errorf("policy %q will fail service config parse", policy)
}
} Type guard
func isRegisteredGRPCLBPolicy(s string) bool {
return balancer.Get(s) != nil
} Try / catch
cc, err := resolver.Build(target, opts)
if err != nil {
if strings.Contains(err.Error(), "failed to initialize service config") {
opts.BalancerPolicy = ""
cc, err = resolver.Build(target, opts)
}
if err != nil { return err }
} Prevention
- Keep BalancerPolicy values consistent with gRPC's registered balancer names.
- Test resolver building for every configured policy in CI.
- Import _ the balancer packages needed so they register.
- Prefer leaving BalancerPolicy empty unless you need a specific balancer.
When it happens
Trigger: Setting opts.BalancerPolicy to a string that is not a registered gRPC load-balancing policy in this binary (e.g. custom policy never registered via balancer.Register), then calling Build/mustBuild.
Common situations: Mismatch between the allowed BalancerPolicy flag values and gRPC's registered balancer names (e.g. registering 'pick_first' in flag but gRPC expects 'pickfirst'); stripped builds where default balancers are not linked in.
Related errors
- %s: unsupported URL host %s
- failed to load static auth plugin. Plugin configured but grp
- gRPCVtctldClient in a SHUTDOWN state
- gRPC connection wait time exceeded
- ErrStreamClosed
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/848e2d2add5aad0c.
Report an issue: GitHub.