{"record":{"id":"2dc530f60fb7831d","repo":"grpc/grpc-go","slug":"randomsubsetting-childpolicy-must-be-specified","errorCode":null,"errorMessage":"randomsubsetting: ChildPolicy must be specified","messagePattern":"randomsubsetting: ChildPolicy must be specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/randomsubsetting/randomsubsetting.go","lineNumber":97,"sourceCode":"\tserviceconfig.LoadBalancingConfig `json:\"-\"`\n\n\tSubsetSize  uint32                         `json:\"subsetSize,omitempty\"`\n\tChildPolicy *iserviceconfig.BalancerConfig `json:\"childPolicy,omitempty\"`\n}\n\nfunc (bb) ParseConfig(s json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {\n\tlbCfg := &lbConfig{}\n\n\t// Ensure that the specified child policy is registered and validates its\n\t// config, if present.\n\tif err := json.Unmarshal(s, lbCfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"randomsubsetting: json.Unmarshal failed for configuration: %s with error: %v\", string(s), err)\n\t}\n\tif lbCfg.SubsetSize == 0 {\n\t\treturn nil, fmt.Errorf(\"randomsubsetting: SubsetSize must be greater than 0\")\n\t}\n\tif lbCfg.ChildPolicy == nil {\n\t\treturn nil, fmt.Errorf(\"randomsubsetting: ChildPolicy must be specified\")\n\t}\n\n\treturn lbCfg, nil\n}\n\nfunc (bb) Name() string {\n\treturn Name\n}\n\ntype subsettingBalancer struct {\n\t*gracefulswitch.Balancer\n\n\tlogger     *internalgrpclog.PrefixLogger\n\tcfg        *lbConfig\n\thashSeed   uint64\n\thashDigest *xxhash.Digest\n}\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/randomsubsetting/randomsubsetting.go#L79-L115","documentation":"Returned by randomsubsetting.ParseConfig (randomsubsetting.go:96-98) when ChildPolicy is nil. random_subsetting selects a random subset of endpoints and then delegates connection/picking to a child LB policy, so a child policy (e.g. round_robin) is mandatory. Without it the policy cannot route.","triggerScenarios":"The config object omits childPolicy, or sets it to null. ParseConfig unmarshals into lbConfig whose ChildPolicy is a pointer, so absence leaves it nil.","commonSituations":"Treating random_subsetting as a standalone policy rather than a wrapper. Forgetting to nest the underlying policy (round_robin / pick_first) under childPolicy.","solutions":["Add a childPolicy entry naming a registered LB policy, most commonly round_robin or pick_first.","Confirm the child policy name is spelled exactly as registered (e.g. \"round_robin\", \"pick_first\")."],"exampleFix":"// before\nraw := `{ \"subsetSize\": 10 }`  // no childPolicy => error\n\n// after\nraw := `{ \"subsetSize\": 10, \"childPolicy\": { \"round_robin\": {} } }`","handlingStrategy":"validation","validationCode":"func validateChildPolicyPresent(raw []byte) error {\n    var c struct{ ChildPolicy json.RawMessage `json:\"childPolicy\"` }\n    _ = json.Unmarshal(raw, &c)\n    if len(c.ChildPolicy) == 0 || string(c.ChildPolicy) == \"null\" {\n        return errors.New(\"childPolicy must be specified\")\n    }\n    return nil\n}","typeGuard":"func hasChildPolicy(c map[string]any) bool {\n    cp, ok := c[\"childPolicy\"]\n    return ok && cp != nil\n}","tryCatchPattern":null,"preventionTips":["Remember random_subsetting wraps a child policy; never ship it alone.","Use a typed config builder that requires a child policy argument."],"tags":["go","grpc","load-balancing","random-subsetting","config"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}