grpc/grpc-go · error
rls: childPolicy config validation failed
Error message
rls: childPolicy config validation failed: %v
What it means
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.
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.
Example fix
// before: weighted_round_robin missing weightedTargets -> child ParseConfig fails
"childPolicy": [ { "weighted_round_robin": {} } ]
// after: use a simpler child policy that the RLS balancer can validate
"childPolicy": [ { "round_robin": {} } ] Defensive patterns
Strategy: validation
Validate before calling
// Reproduce the RLS balancer's child-config validation with a dummy target
// so config errors surface before deployment.
func validateChildPolicyConfig(builder balancer.Builder, raw json.RawMessage, targetField string) error {
parser, ok := builder.(balancer.ConfigParser)
if !ok {
return errors.New("child balancer does not implement ConfigParser")
}
var m map[string]json.RawMessage
if err := json.Unmarshal(raw, &m); err != nil {
return err
}
m[targetField], _ = json.Marshal("target_name_to_be_filled_in_later")
cfg, err := json.Marshal(m)
if err != nil {
return err
}
if _, err := parser.ParseConfig(cfg); err != nil {
return fmt.Errorf("child policy rejects config: %w", err)
}
return nil
} Type guard
func childPolicyAcceptsConfig(builder balancer.Builder, raw json.RawMessage, targetField string) bool {
return validateChildPolicyConfig(builder, raw, targetField) == nil
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- rls: childPolicy with config does not support config parsing
- rls: childPolicyConfigTargetFieldName field is not set in…
- rls: invalid childPolicy config: no supported policies…
- rls: invalid childPolicy: entry
- rls: json unmarshal failed for child policy config
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/eeb95f82b83a758f.
Report an issue: GitHub.
Appendix: source
Thrown at balancer/rls/config.go:318
return "", nil, fmt.Errorf("rls: childPolicy %q with config %q does not support config parsing", name, string(rawCfg))
}
// To validate child policy configs we do the following:
// - unmarshal the raw JSON bytes of the child policy config into a map
// - add an entry with key set to `target_field_name` and a dummy value
// - marshal the map back to JSON and parse the config using the parser
// retrieved previously
var childConfig map[string]json.RawMessage
if err := json.Unmarshal(rawCfg, &childConfig); err != nil {
return "", nil, fmt.Errorf("rls: json unmarshal failed for child policy config %q: %v", string(rawCfg), err)
}
childConfig[targetFieldName], _ = json.Marshal(dummyChildPolicyTarget)
jsonCfg, err := json.Marshal(childConfig)
if err != nil {
return "", nil, fmt.Errorf("rls: json marshal failed for child policy config {%+v}: %v", childConfig, err)
}
if _, err := parser.ParseConfig(jsonCfg); err != nil {
return "", nil, fmt.Errorf("rls: childPolicy config validation failed: %v", err)
}
return name, childConfig, nil
}
return "", nil, fmt.Errorf("rls: invalid childPolicy config: no supported policies found in %+v", childPolicies)
}
func convertDuration(d *durationpb.Duration) (time.Duration, error) {
if d == nil {
return 0, nil
}
return d.AsDuration(), d.CheckValid()
}
View on GitHub (pinned to 0c51461d27)