grpc/grpc-go · critical
grpc: the provided default service config is invalid: %v
Error message
grpc: the provided default service config is invalid: %v
What it means
WithDefaultServiceConfig(s) stores a raw JSON service config applied as fallback when the resolver provides none (or when WithDisableServiceConfig is set). During NewClient, clientconn.go:229-233 parses it via parseServiceConfig; if parsing fails, NewClient returns nil and this error, because a broken default config would leave the channel unable to pick a balancer.
Source
Thrown at clientconn.go:232
if err := cc.initParsedTargetAndResolverBuilder(); err != nil {
return nil, err
}
for _, opt := range globalPerTargetDialOptions {
opt.DialOptionForTarget(cc.parsedTarget.URL).apply(&cc.dopts)
}
chainUnaryClientInterceptors(cc)
chainStreamClientInterceptors(cc)
if err := cc.validateTransportCredentials(); err != nil {
return nil, err
}
if cc.dopts.defaultServiceConfigRawJSON != nil {
scpr := parseServiceConfig(*cc.dopts.defaultServiceConfigRawJSON, cc.dopts.maxCallAttempts)
if scpr.Err != nil {
return nil, fmt.Errorf("%s: %v", invalidDefaultServiceConfigErrPrefix, scpr.Err)
}
cc.dopts.defaultServiceConfig, _ = scpr.Config.(*ServiceConfig)
}
cc.keepaliveParams = cc.dopts.copts.KeepaliveParams
if err = cc.initAuthority(); err != nil {
return nil, err
}
// Register ClientConn with channelz. Note that this is only done after
// channel creation cannot fail.
cc.channelzRegistration(target)
channelz.Infof(logger, cc.channelz, "parsed dial target is: %#v", cc.parsedTarget)
channelz.Infof(logger, cc.channelz, "Channel authority set to %q", cc.authority)
cc.csMgr = newConnectivityStateManager(cc.ctx, cc.channelz)
cc.pickerWrapper = newPickerWrapper()
View on GitHub (pinned to 0c51461d27)
Solutions
- Run the JSON through a validator and against the gRPC service config schema (https://github.com/grpc/grpc/blob/master/doc/service_config.md).
- Ensure any balancer referenced in loadBalancingConfig is registered (import its package side-effect, e.g., _ "google.golang.org/grpc/balancer/weightedroundrobin").
- Simplify to a known-good config first (e.g., {"loadBalancingConfig":[{"pick_first":{}}]}) then add fields back incrementally.
Example fix
// before
cc, err := grpc.NewClient(target, grpc.WithDefaultServiceConfig(
`{"loadBalancingConfig":[{"round_robin"}]}`, // missing colon/braces
)
// after
cc, err := grpc.NewClient(target, grpc.WithDefaultServiceConfig(
`{"loadBalancingConfig":[{"round_robin":{}}]}`,
)) Defensive patterns
Strategy: validation
Validate before calling
func validateDefaultServiceConfigJSON(js string) error {
pr := parseServiceConfig(js, 1) // maxAttempts; or use serviceconfig.Parse via the balancer registry
return pr.Err
} Try / catch
// always check the error from NewClient
cc, err := grpc.NewClient(target, grpc.WithDefaultServiceConfig(sc))
if err != nil {
return fmt.Errorf("invalid default service config: %w", err)
} Prevention
- Validate the default service config JSON against the gRPC service_config.md schema.
- Import any custom balancer packages so their names resolve in loadBalancingConfig.
- Start from a minimal known-good config and add fields incrementally with a test.
When it happens
Trigger: Calling grpc.NewClient(target, grpc.WithDefaultServiceConfig(badJSON)) where badJSON is invalid JSON, references an unregistered balancer, or has malformed loadBalancingConfig/retryPolicy fields. parseServiceConfig returns a non-nil scpr.Err and clientconn.go:232 wraps it.
Common situations: A typo in the service config JSON string; referencing a balancer name that is not registered (e.g., custom balancer not imported); malformed retry policy; quoting errors when building the string programmatically.
Related errors
- cannot have a leading slash
- / must come in between service and method, only one /
- method name must be non empty
- cannot have exclude and a '*' wildcard
- empty string is not a valid method binary logging config
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/66e1c9873e9557ad.
Report an issue: GitHub.