{"record":{"id":"910784ce66605db6","repo":"grpc/grpc-go","slug":"rls-json-unmarshal-failed-for-child-policy-config","errorCode":null,"errorMessage":"rls: json unmarshal failed for child policy config %q: %v","messagePattern":"rls: json unmarshal failed for child policy config %q: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/config.go","lineNumber":310,"sourceCode":"\t\tfor name, rawCfg = range config {\n\t\t}\n\t\tbuilder := balancer.Get(name)\n\t\tif builder == nil {\n\t\t\tcontinue\n\t\t}\n\t\tparser, ok := builder.(balancer.ConfigParser)\n\t\tif !ok {\n\t\t\treturn \"\", nil, fmt.Errorf(\"rls: childPolicy %q with config %q does not support config parsing\", name, string(rawCfg))\n\t\t}\n\n\t\t// To validate child policy configs we do the following:\n\t\t// - unmarshal the raw JSON bytes of the child policy config into a map\n\t\t// - add an entry with key set to `target_field_name` and a dummy value\n\t\t// - marshal the map back to JSON and parse the config using the parser\n\t\t// retrieved previously\n\t\tvar childConfig map[string]json.RawMessage\n\t\tif err := json.Unmarshal(rawCfg, &childConfig); err != nil {\n\t\t\treturn \"\", nil, fmt.Errorf(\"rls: json unmarshal failed for child policy config %q: %v\", string(rawCfg), err)\n\t\t}\n\t\tchildConfig[targetFieldName], _ = json.Marshal(dummyChildPolicyTarget)\n\t\tjsonCfg, err := json.Marshal(childConfig)\n\t\tif err != nil {\n\t\t\treturn \"\", nil, fmt.Errorf(\"rls: json marshal failed for child policy config {%+v}: %v\", childConfig, err)\n\t\t}\n\t\tif _, err := parser.ParseConfig(jsonCfg); err != nil {\n\t\t\treturn \"\", nil, fmt.Errorf(\"rls: childPolicy config validation failed: %v\", err)\n\t\t}\n\t\treturn name, childConfig, nil\n\t}\n\treturn \"\", nil, fmt.Errorf(\"rls: invalid childPolicy config: no supported policies found in %+v\", childPolicies)\n}\n\nfunc convertDuration(d *durationpb.Duration) (time.Duration, error) {\n\tif d == nil {\n\t\treturn 0, nil\n\t}","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/config.go#L292-L328","documentation":"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.","triggerScenarios":"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}}].","commonSituations":"Hand-editing service config JSON; YAML-to-JSON tools producing non-strict output; concatenating config fragments without re-validating; copy-paste introducing smart quotes.","solutions":["Run the full service config through a JSON validator (jq ., jsonschema) before deploying.","Fix the specific syntax error reported in the trailing %v (it names line/position).","Generate configs programmatically with encoding/json rather than string concatenation."],"exampleFix":"// before\n\"childPolicy\": [{ \"round_robin\": { 'shard': 1 } }]\n// after\n\"childPolicy\": [{ \"round_robin\": { \"shard\": 1 } }]","handlingStrategy":"validation","validationCode":"func validateChildPolicyJSON(childPolicy []map[string]json.RawMessage) error {\n    for i, entry := range childPolicy {\n        for name, raw := range entry {\n            var m map[string]json.RawMessage\n            if err := json.Unmarshal(raw, &m); err != nil {\n                return fmt.Errorf(\"childPolicy[%d].%s: invalid JSON: %w\", i, name, err)\n            }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate the whole service config with jq before deploying.","Generate configs with encoding/json instead of string templates.","Reject single-quoted JSON or trailing commas in your config lint."],"tags":["rls","service-config","config-validation","go","grpc","json"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}