grpc/grpc-go · error
invalid loadBalancingConfig: no supported policies found in
Error message
invalid loadBalancingConfig: no supported policies found in %v
What it means
Fires at serviceconfig.go:125 after BalancerConfig.UnmarshalJSON walks every loadBalancingConfig entry and finds none whose policy name maps to a registered balancer. gRPC iterates entries in order and uses the first supported policy; if the list contains only unknown policy names, the whole service config is rejected as invalid rather than silently falling back.
Solutions
- Cross-check each policy name in the error's %v list against balancer.Get registrations; blank-import the missing package (e.g. _ "google.golang.org/grpc/balancer/roundrobin").
- Verify the spelling of policy names; note built-in names like "pick_first" and "round_robin" use snake_case.
- If a policy is genuinely unavailable on this client version, either upgrade the client or have the config producer prepend a policy the client does support.
- For xDS-managed clients, ensure the xds resolver and its balancers are imported and the client version matches the config source.
Example fix
// before: service config only references grpclb, which is not imported
// "loadBalancingConfig": [{"grpclb": {}}]
// after: import the balancer and/or reference a supported policy
import _ "google.golang.org/grpc/balancer/grpclb"
// or
// "loadBalancingConfig": [{"round_robin": {}}, {"grpclb": {}}] Defensive patterns
Strategy: validation
Validate before calling
import (
"google.golang.org/grpc/balancer"
_ "google.golang.org/grpc/balancer/roundrobin"
_ "google.golang.org/grpc/balancer/grpclb"
)
func ensureBalancersRegistered(names []string) error {
for _, n := range names {
if balancer.Get(n) == nil {
return fmt.Errorf("balancer %q is not registered; import its package", n)
}
}
return nil
} Try / catch
var bc svcconfig.BalancerConfig
if err := json.Unmarshal(raw, &bc); err != nil {
if strings.Contains(err.Error(), "no supported policies found") {
// import the referenced balancer packages, or prepend a supported policy
}
return err
} Prevention
- Blank-import every balancer package your config references.
- Use snake_case policy names exactly as registered (round_robin, pick_first).
- When shipping xDS-managed clients, ensure all needed balancers are linked.
When it happens
Trigger: A service config whose loadBalancingConfig array lists only balancer names that are not registered in the binary. Examples: [{"grpclb": {}}] when the grpclb balancer was never imported or was removed; [{"rls": {}}] without importing the RLS balancer; policy names from a newer gRPC than the client.
Common situations: Using a service config designed for a different gRPC feature set (xDS/RLS/cds) on a plain client; a balancer package removed or never blank-imported; version skew between the control plane emitting config and the client consuming it; using "round_robin" spelling when the registered name differs.
Related errors
- error parsing loadBalancingConfig for policy
- invalid loadBalancingConfig: entry
- duplicated name
- failed to parse child policy config. This should never…
- grpc: the provided default service config is invalid
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/3ea577954e9b6415.
Report an issue: GitHub.
Appendix: source
Thrown at internal/serviceconfig/serviceconfig.go:125
if string(jsonCfg) != "{}" {
logger.Warningf("non-empty balancer configuration %q, but balancer does not implement ParseConfig", string(jsonCfg))
}
// Stop at this, though the builder doesn't support parsing config.
return nil
}
cfg, err := parser.ParseConfig(jsonCfg)
if err != nil {
return fmt.Errorf("error parsing loadBalancingConfig for policy %q: %v", name, err)
}
bc.Config = cfg
return nil
}
// This is reached when the for loop iterates over all entries, but didn't
// return. This means we had a loadBalancingConfig slice but did not
// encounter a registered policy. The config is considered invalid in this
// case.
return fmt.Errorf("invalid loadBalancingConfig: no supported policies found in %v", names)
}
// MethodConfig defines the configuration recommended by the service providers for a
// particular method.
type MethodConfig struct {
// WaitForReady indicates whether RPCs sent to this method should wait until
// the connection is ready by default (!failfast). The value specified via the
// gRPC client API will override the value set here.
WaitForReady *bool
// Timeout is the default timeout for RPCs sent to this method. The actual
// deadline used will be the minimum of the value specified here and the value
// set by the application via the gRPC client API. If either one is not set,
// then the other will be used. If neither is set, then the RPC has no deadline.
Timeout *time.Duration
// MaxReqSize is the maximum allowed payload size for an individual request in a
// stream (client->server) in bytes. The size which is measured is the serialized
// payload after per-message compression (but before stream compression) in bytes.
// The actual value used is the minimum of the value specified here and the value setView on GitHub (pinned to 0c51461d27)