grpc/grpc-go · error
rls: childPolicy with config does not support config parsing
Error message
rls: childPolicy %q with config %q does not support config parsing
What it means
Emitted from parseChildPolicyConfigs (config.go:300) when the balancer.Builder registered under the child-policy name does not implement the balancer.ConfigParser interface. The RLS balancer must parse and validate the child policy config (to inject the target field), so a builder that exposes no ConfigParser is unusable as an RLS child.
Solutions
- Switch the childPolicy to a balancer that implements ConfigParser (round_robin, weighted_round_robin, cds, xds_cluster_resolver, etc.).
- If you maintain the child balancer, implement balancer.ConfigParser (ParseConfig(json.RawMessage) (LoadBalancingConfig, error)) on its builder.
- Reorder the childPolicy array so a parser-supporting policy is listed first if you must keep the non-parser one as a fallback name (it will be skipped, not error, only if it is not the first registered).
Example fix
// before: 'custom_lb' builder has no ConfigParser
"childPolicy": [ { "custom_lb": {} } ]
// after: use a balancer that supports config parsing
"childPolicy": [ { "round_robin": {} } ]
// or implement on custom_lb:
// func (b *customLBBuilder) ParseConfig(raw json.RawMessage) (serviceconfig.LoadBalancingConfig, error) { ... } Defensive patterns
Strategy: type-guard
Validate before calling
func childPolicySupportsParsing(name string) bool {
b := balancer.Get(name)
if b == nil {
return false
}
_, ok := b.(balancer.ConfigParser)
return ok
} Type guard
func isConfigParser(b balancer.Builder) bool {
_, ok := b.(balancer.ConfigParser)
return ok
} Prevention
- Prefer core balancers (round_robin, pick_first) that implement ConfigParser.
- If you maintain a child balancer, implement balancer.ConfigParser on its Builder.
- Unit-test that balancer.Get(name).(balancer.ConfigParser) succeeds for each child you list.
When it happens
Trigger: A childPolicy entry names a registered balancer whose Builder type does not satisfy balancer.ConfigParser (no ParseConfig method). The entry is the first registered builder encountered, so the error is immediate rather than skipped.
Common situations: Using a minimal/custom balancer that was registered with balancer.Register but whose author did not implement ConfigParser; using the legacy 'pick_first'/'round_robin' from a very old or forked module where the parser interface was not implemented; a balancer that is config-less by design.
Related errors
- rls: childPolicy config validation failed
- rls: invalid childPolicy config: no supported policies…
- failed to create child policy of type
- failed to marshal child policy config %+v
- failed to marshal child policy target
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/71b4fbc2b3992463.
Report an issue: GitHub.
Appendix: source
Thrown at balancer/rls/config.go:300
// parseChildPolicyConfigs iterates through the list of child policies and picks
// the first registered policy and validates its config.
func parseChildPolicyConfigs(childPolicies []map[string]json.RawMessage, targetFieldName string) (string, map[string]json.RawMessage, error) {
for i, config := range childPolicies {
if len(config) != 1 {
return "", nil, fmt.Errorf("rls: invalid childPolicy: entry %v does not contain exactly 1 policy/config pair: %q", i, config)
}
var name string
var rawCfg json.RawMessage
for name, rawCfg = range config {
}
builder := balancer.Get(name)
if builder == nil {
continue
}
parser, ok := builder.(balancer.ConfigParser)
if !ok {
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)View on GitHub (pinned to 0c51461d27)