{"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/0c51461d27177d997e14c642fe18c11668fc09a3/balancer/rls/config.go#L300-L331","documentation":"Emitted from parseChildPolicyConfigs (config.go:318) when the child policy's own ConfigParser.ParseConfig rejects the config after the RLS balancer inserted the dummy target field (dummyChildPolicyTarget = \"target_name_to_be_filled_in_later\"). The child balancer's own validation logic is the source of the rejection; the inner error is wrapped.","triggerScenarios":"The child policy config is structurally valid JSON but semantically invalid per the child balancer: a required field is missing, a value is out of range, or the target field placeholder is rejected by the child's field validation.","commonSituations":"weighted_round_robin config missing weightedTargets; a cds/xds child policy used outside an xDS context where it cannot resolve; round_robin/priority config with invalid nested structure; a child policy version that renamed a required field.","solutions":["Read the wrapped %v error from the child balancer; it names the exact failing constraint.","Provide the missing/invalid fields required by the chosen child policy (see that balancer's ParseConfig docs).","Test the child config in isolation by invoking its ParseConfig with the dummy target injected.","If the child policy cannot tolerate the dummy target placeholder (e.g. it strictly validates hostnames), switch to a child policy whose config parser accepts arbitrary target strings."],"exampleFix":"// before: weighted_round_robin missing weightedTargets -> child ParseConfig fails\n\"childPolicy\": [ { \"weighted_round_robin\": {} } ]\n\n// after: use a simpler child policy that the RLS balancer can validate\n\"childPolicy\": [ { \"round_robin\": {} } ]","handlingStrategy":"validation","validationCode":"// Reproduce the RLS balancer's child-config validation with a dummy target\n// so config errors surface before deployment.\nfunc validateChildPolicyConfig(builder balancer.Builder, raw json.RawMessage, targetField string) error {\n    parser, ok := builder.(balancer.ConfigParser)\n    if !ok {\n        return errors.New(\"child balancer does not implement ConfigParser\")\n    }\n    var m map[string]json.RawMessage\n    if err := json.Unmarshal(raw, &m); err != nil {\n        return err\n    }\n    m[targetField], _ = json.Marshal(\"target_name_to_be_filled_in_later\")\n    cfg, err := json.Marshal(m)\n    if err != nil {\n        return err\n    }\n    if _, err := parser.ParseConfig(cfg); err != nil {\n        return fmt.Errorf(\"child policy rejects config: %w\", err)\n    }\n    return nil\n}","typeGuard":"func childPolicyAcceptsConfig(builder balancer.Builder, raw json.RawMessage, targetField string) bool {\n    return validateChildPolicyConfig(builder, raw, targetField) == nil\n}","tryCatchPattern":null,"preventionTips":["Read the wrapped error from the child balancer to find the exact failing constraint.","Unit-test the child config via the child's own ParseConfig before shipping.","Prefer child policies (round_robin) whose config is permissive when you do not need advanced features."],"tags":["rls","child-policy","validation","config-parser"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}