grpc/grpc-go · error

rls: json unmarshal failed for child policy config %q: %v

Error message

rls: json unmarshal failed for child policy config %q: %v

What it means

Before RLS can ask the child policy to validate its config, it json.Unmarshal's the raw child config bytes into a map[string]json.RawMessage to inject the target field name. If those bytes are not valid JSON, this unmarshal fails and the error (including the underlying json error) is returned.

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 03255a9237)

Solutions

  1. Run the full service config through a JSON validator (jq ., jsonschema) before deploying.
  2. Fix the specific syntax error reported in the trailing %v (it names line/position).
  3. Generate configs programmatically with encoding/json rather than string concatenation.

Example fix

// before
"childPolicy": [{ "round_robin": { 'shard': 1 } }]
// after
"childPolicy": [{ "round_robin": { "shard": 1 } }]
Defensive patterns

Strategy: validation

Validate before calling

func validateChildPolicyJSON(childPolicy []map[string]json.RawMessage) error {
    for i, entry := range childPolicy {
        for name, raw := range entry {
            var m map[string]json.RawMessage
            if err := json.Unmarshal(raw, &m); err != nil {
                return fmt.Errorf("childPolicy[%d].%s: invalid JSON: %w", i, name, err)
            }
        }
    }
    return nil
}

Prevention

When it happens

Trigger: The value side of a childPolicy entry is malformed JSON: trailing comma, unquoted string, single quotes, or a stray character. E.g. [{"round_robin": {broken}}].

Common situations: Hand-editing service config JSON; YAML-to-JSON tools producing non-strict output; concatenating config fragments without re-validating; copy-paste introducing smart quotes.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/910784ce66605db6. Report an issue: GitHub.