{"record":{"id":"eeb95f82b83a758f","repo":"grpc/grpc-go","slug":"rls-childpolicy-config-validation-failed-v","errorCode":null,"errorMessage":"rls: childPolicy config validation failed: %v","messagePattern":"rls: childPolicy config validation failed: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/config.go","lineNumber":318,"sourceCode":"\t\t\treturn \"\", nil, fmt.Errorf(\"rls: childPolicy %q with config %q does not support config parsing\", name, string(rawCfg))\n\t\t}\n\n\t\t// To validate child policy configs we do the following:\n\t\t// - unmarshal the raw JSON bytes of the child policy config into a map\n\t\t// - add an entry with key set to `target_field_name` and a dummy value\n\t\t// - marshal the map back to JSON and parse the config using the parser\n\t\t// retrieved previously\n\t\tvar childConfig map[string]json.RawMessage\n\t\tif err := json.Unmarshal(rawCfg, &childConfig); err != nil {\n\t\t\treturn \"\", nil, fmt.Errorf(\"rls: json unmarshal failed for child policy config %q: %v\", string(rawCfg), err)\n\t\t}\n\t\tchildConfig[targetFieldName], _ = json.Marshal(dummyChildPolicyTarget)\n\t\tjsonCfg, err := json.Marshal(childConfig)\n\t\tif err != nil {\n\t\t\treturn \"\", nil, fmt.Errorf(\"rls: json marshal failed for child policy config {%+v}: %v\", childConfig, err)\n\t\t}\n\t\tif _, err := parser.ParseConfig(jsonCfg); err != nil {\n\t\t\treturn \"\", nil, fmt.Errorf(\"rls: childPolicy config validation failed: %v\", err)\n\t\t}\n\t\treturn name, childConfig, nil\n\t}\n\treturn \"\", nil, fmt.Errorf(\"rls: invalid childPolicy config: no supported policies found in %+v\", childPolicies)\n}\n\nfunc convertDuration(d *durationpb.Duration) (time.Duration, error) {\n\tif d == nil {\n\t\treturn 0, nil\n\t}\n\treturn d.AsDuration(), d.CheckValid()\n}\n","sourceCodeStart":300,"sourceCodeEnd":331,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/config.go#L300-L331","documentation":"RLS successfully parsed the child policy's config structurally and handed it (with a dummy target injected) to the child policy's own ConfigParser.ParseConfig. That parser returned an error, meaning the child config violates the child policy's rules. The %v is the child policy's own error message.","triggerScenarios":"Passing a syntactically valid but semantically invalid config to the child — e.g. weighted_round_robin with a negative errorUtilizationPenalty, or round_robin with an unknown field when strict parsing is on. The child policy name was accepted but its contents were rejected.","commonSituations":"Version skew (using a field only supported in a newer gRPC); typo'd field names that look valid; supplying out-of-range numeric values; copying a config example for a different LB policy.","solutions":["Read the trailing %v — it is the child policy's specific complaint (e.g. 'wrr: errorUtilizationPenalty must be non-negative').","Correct the offending field per that child policy's documentation.","Confirm the field is supported in your gRPC-Go version before reusing it."],"exampleFix":"// before\n\"childPolicy\": [{ \"weighted_round_robin\": { \"errorUtilizationPenalty\": -1 } }]\n// after\n\"childPolicy\": [{ \"weighted_round_robin\": { \"errorUtilizationPenalty\": 1 } }]","handlingStrategy":"validation","validationCode":"func validateChildConfigViaParser(childPolicy []map[string]json.RawMessage, targetField string) error {\n    for _, entry := range childPolicy {\n        for name, raw := range entry {\n            b := balancer.Get(name)\n            if b == nil { continue }\n            p, ok := b.(balancer.ConfigParser)\n            if !ok { continue }\n            var m map[string]json.RawMessage\n            _ = json.Unmarshal(raw, &m)\n            m[targetField], _ = json.Marshal(\"dummy\")\n            js, _ := json.Marshal(m)\n            if _, err := p.ParseConfig(js); err != nil {\n                return fmt.Errorf(\"child %s config invalid: %w\", name, err)\n            }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mirror RLS's own validation (inject dummy target, call child ParseConfig) in your config CI.","Read the child policy's specific error message — it points at the bad field.","Confirm each field is supported in your gRPC-Go version."],"tags":["rls","service-config","config-validation","go","grpc","child-policy"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}