{"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/0c51461d27177d997e14c642fe18c11668fc09a3/balancer/rls/config.go#L292-L328","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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\":{...}}})."],"exampleFix":"// before\n\"childPolicy\": [ { \"round_robin\": \"\" } ]\n\n// after\n\"childPolicy\": [ { \"round_robin\": {} } ]","handlingStrategy":"validation","validationCode":"func validateChildConfigIsObject(raw json.RawMessage) error {\n    var m map[string]json.RawMessage\n    if err := json.Unmarshal(raw, &m); err != nil {\n        return fmt.Errorf(\"child policy config is not a JSON object: %w\", err)\n    }\n    return nil\n}","typeGuard":"func childConfigIsJSONObject(raw json.RawMessage) bool {\n    var m map[string]json.RawMessage\n    return json.Unmarshal(raw, &m) == nil\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["rls","child-policy","json","validation"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}