{"record":{"id":"3ea577954e9b6415","repo":"grpc/grpc-go","slug":"invalid-loadbalancingconfig-no-supported-policies","errorCode":null,"errorMessage":"invalid loadBalancingConfig: no supported policies found in %v","messagePattern":"invalid loadBalancingConfig: no supported policies found in (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/serviceconfig/serviceconfig.go","lineNumber":125,"sourceCode":"\t\t\tif string(jsonCfg) != \"{}\" {\n\t\t\t\tlogger.Warningf(\"non-empty balancer configuration %q, but balancer does not implement ParseConfig\", string(jsonCfg))\n\t\t\t}\n\t\t\t// Stop at this, though the builder doesn't support parsing config.\n\t\t\treturn nil\n\t\t}\n\n\t\tcfg, err := parser.ParseConfig(jsonCfg)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error parsing loadBalancingConfig for policy %q: %v\", name, err)\n\t\t}\n\t\tbc.Config = cfg\n\t\treturn nil\n\t}\n\t// This is reached when the for loop iterates over all entries, but didn't\n\t// return. This means we had a loadBalancingConfig slice but did not\n\t// encounter a registered policy. The config is considered invalid in this\n\t// case.\n\treturn fmt.Errorf(\"invalid loadBalancingConfig: no supported policies found in %v\", names)\n}\n\n// MethodConfig defines the configuration recommended by the service providers for a\n// particular method.\ntype MethodConfig struct {\n\t// WaitForReady indicates whether RPCs sent to this method should wait until\n\t// the connection is ready by default (!failfast). The value specified via the\n\t// gRPC client API will override the value set here.\n\tWaitForReady *bool\n\t// Timeout is the default timeout for RPCs sent to this method. The actual\n\t// deadline used will be the minimum of the value specified here and the value\n\t// set by the application via the gRPC client API.  If either one is not set,\n\t// then the other will be used.  If neither is set, then the RPC has no deadline.\n\tTimeout *time.Duration\n\t// MaxReqSize is the maximum allowed payload size for an individual request in a\n\t// stream (client->server) in bytes. The size which is measured is the serialized\n\t// payload after per-message compression (but before stream compression) in bytes.\n\t// The actual value used is the minimum of the value specified here and the value set","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/serviceconfig/serviceconfig.go#L107-L143","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: service config only references grpclb, which is not imported\n// \"loadBalancingConfig\": [{\"grpclb\": {}}]\n\n// after: import the balancer and/or reference a supported policy\nimport _ \"google.golang.org/grpc/balancer/grpclb\"\n// or\n// \"loadBalancingConfig\": [{\"round_robin\": {}}, {\"grpclb\": {}}]","handlingStrategy":"validation","validationCode":"import (\n    \"google.golang.org/grpc/balancer\"\n    _ \"google.golang.org/grpc/balancer/roundrobin\"\n    _ \"google.golang.org/grpc/balancer/grpclb\"\n)\n\nfunc ensureBalancersRegistered(names []string) error {\n    for _, n := range names {\n        if balancer.Get(n) == nil {\n            return fmt.Errorf(\"balancer %q is not registered; import its package\", n)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"var bc svcconfig.BalancerConfig\nif err := json.Unmarshal(raw, &bc); err != nil {\n    if strings.Contains(err.Error(), \"no supported policies found\") {\n        // import the referenced balancer packages, or prepend a supported policy\n    }\n    return err\n}","preventionTips":["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."],"tags":["config","loadbalancing","service-config","registration","version-skew"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}