grpc/grpc-go · error
rls: json unmarshal failed for child policy config
Error message
rls: json unmarshal failed for child policy config %q: %v
What it means
Emitted from parseChildPolicyConfigs (config.go:310) when json.Unmarshal of a child policy's raw config into map[string]json.RawMessage fails. The child config must be a JSON object so the RLS balancer can inject the target field; a non-object (array, string, number) or syntactically invalid JSON triggers this.
Solutions
- Make each child policy config a JSON object, even if empty: {"round_robin":{}}.
- Run the full config through 'jq' to confirm every child config parses as an object.
- If the child policy needs parameters, provide them as an object (e.g. {"weighted_round_robin":{"weightedTargets":{...}}}).
Example fix
// before
"childPolicy": [ { "round_robin": "" } ]
// after
"childPolicy": [ { "round_robin": {} } ] Defensive patterns
Strategy: validation
Validate before calling
func validateChildConfigIsObject(raw json.RawMessage) error {
var m map[string]json.RawMessage
if err := json.Unmarshal(raw, &m); err != nil {
return fmt.Errorf("child policy config is not a JSON object: %w", err)
}
return nil
} Type guard
func childConfigIsJSONObject(raw json.RawMessage) bool {
var m map[string]json.RawMessage
return json.Unmarshal(raw, &m) == nil
} Prevention
- Use {} for config-less child policies, not "" or null.
- Lint that every child config value starts with '{'.
- Generate child configs from typed structs via encoding/json.
When it happens
Trigger: A childPolicy config value that is JSON-valid but not an object (e.g. "round_robin": []), or syntactically invalid JSON bytes inside an otherwise-valid outer config.
Common situations: Setting "round_robin": "" or "round_robin": null; a config generator that emits the config as a JSON string instead of an object; trailing commas inside the child config.
Related errors
- failed to marshal child policy config %+v
- failed to marshal child policy target
- rls: childPolicy config validation failed
- rls: childPolicyConfigTargetFieldName field is not set in…
- rls: invalid childPolicy config: no supported policies…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/910784ce66605db6.
Report an issue: GitHub.
Appendix: source
Thrown at balancer/rls/config.go:310
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)
}
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
}View on GitHub (pinned to 0c51461d27)