grpc/grpc-go · error
rls: childPolicy %q with config %q does not support config p
Error message
rls: childPolicy %q with config %q does not support config parsing
What it means
RLS delegates actual subchannel selection to a child LB policy, and to validate the child config it needs the policy to implement balancer.ConfigParser. If the resolved builder (registered via balancer.Get(name)) does not implement ConfigParser, RLS cannot parse/validate a config for it, so it errors rather than silently accepting an unvalidated config.
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 03255a9237)
Solutions
- Use a child policy that supports config parsing (round_robin, pick_first, weighted_round_robin are standard).
- If the named policy intentionally takes no config, pass an empty config object and confirm the build registers a ConfigParser for it; otherwise switch policies.
- Upgrade gRPC-Go — ConfigParser support for standard policies has been broadened over releases.
Example fix
// before
"childPolicy": [{ "custom_experimental_lb": { "someField": 1 } }]
// after
"childPolicy": [{ "round_robin": {} }] Defensive patterns
Strategy: validation
Validate before calling
func validateChildPolicyRegistered(childPolicy []map[string]json.RawMessage) error {
for _, entry := range childPolicy {
for name := range entry {
b := balancer.Get(name)
if b == nil {
continue // handled by error 127
}
if _, ok := b.(balancer.ConfigParser); !ok {
return fmt.Errorf("policy %q does not implement ConfigParser", name)
}
}
}
return nil
} Prevention
- Prefer the standard policies (round_robin, pick_first, weighted_round_robin) as RLS children.
- Blank-import any custom balancer package so its init() registers it before config parse.
- Confirm ConfigParser support before standardizing on a child policy.
When it happens
Trigger: Naming a child policy that exists (is registered) but takes no parseable JSON config, or providing a config object for one. E.g. naming a custom or built-in balancer that has no ParseConfig method while also passing it a non-empty config block.
Common situations: Using an older/preview balancer that lacks ConfigParser; referencing a policy by a wrong/legacy name; supplying a config to a no-config policy like a bare pick_first in some builds.
Related errors
- rls: invalid childPolicy: entry %v does not contain exactly
- rls: childPolicy config validation failed: %v
- rls: invalid childPolicy config: no supported policies found
- rls: stale_age is set, but max_age is not in route lookup co
- rls: cache_size_bytes must be set to a non-zero value: %+v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/71b4fbc2b3992463.
Report an issue: GitHub.