{"record":{"id":"7b72ae12e0d5e894","repo":"grpc/grpc-go","slug":"rls-invalid-childpolicy-entry-v-does-not-contai","errorCode":null,"errorMessage":"rls: invalid childPolicy: entry %v does not contain exactly 1 policy/config pair: %q","messagePattern":"rls: invalid childPolicy: entry (.+?) does not contain exactly 1 policy/config pair: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/config.go","lineNumber":287,"sourceCode":"\t\tcacheSizeBytes = maxCacheSize\n\t}\n\treturn &lbConfig{\n\t\tkbMap:                kbMap,\n\t\tlookupService:        lookupService,\n\t\tlookupServiceTimeout: lookupServiceTimeout,\n\t\tmaxAge:               maxAge,\n\t\tstaleAge:             staleAge,\n\t\tcacheSizeBytes:       cacheSizeBytes,\n\t\tdefaultTarget:        rlsProto.GetDefaultTarget(),\n\t}, nil\n}\n\n// parseChildPolicyConfigs iterates through the list of child policies and picks\n// the first registered policy and validates its config.\nfunc parseChildPolicyConfigs(childPolicies []map[string]json.RawMessage, targetFieldName string) (string, map[string]json.RawMessage, error) {\n\tfor i, config := range childPolicies {\n\t\tif len(config) != 1 {\n\t\t\treturn \"\", nil, fmt.Errorf(\"rls: invalid childPolicy: entry %v does not contain exactly 1 policy/config pair: %q\", i, config)\n\t\t}\n\n\t\tvar name string\n\t\tvar rawCfg json.RawMessage\n\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","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/config.go#L269-L305","documentation":"The childPolicy field in an RLS service config is a list of single-entry maps, each mapping one LB policy name to its config (the prioritized child policy list). parseChildPolicyConfigs requires every list entry to have exactly one policy->config key; an entry with zero or multiple keys is ambiguous and rejected.","triggerScenarios":"A ChildPolicy JSON array entry that is {} (empty object) or {\"pick_first\":{...},\"round_robin\":{...}} (two policies in one entry). The error reports the offending entry index and the map contents.","commonSituations":"Hand-authoring the child policy list as a flat object instead of a list of single-key maps; YAML->JSON conversion collapsing structure; misunderstanding the gRPC LB policy grammar where each priority is a separate one-element map.","solutions":["Make each array element a single-key object: [{\"pick_first\":{}}, {\"round_robin\":{}}] for fallback ordering, not [{\"pick_first\":{},\"round_robin\":{}}].","Remove any empty {} entries from the ChildPolicy array.","Validate the array shape before deploying: every element must satisfy len(element)==1."],"exampleFix":"// before\n\"childPolicy\": [\n  {\"pick_first\": {}, \"round_robin\": {}}\n]\n// after\n\"childPolicy\": [\n  {\"pick_first\": {}},\n  {\"round_robin\": {}}\n]","handlingStrategy":"validation","validationCode":"func validateChildPolicyShape(childPolicy []map[string]json.RawMessage) error {\n    if len(childPolicy) == 0 {\n        return fmt.Errorf(\"childPolicy list is empty\")\n    }\n    for i, entry := range childPolicy {\n        if len(entry) != 1 {\n            return fmt.Errorf(\"childPolicy[%d] must have exactly 1 policy/config pair, got %d\", i, len(entry))\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember the gRPC childPolicy grammar: a list of single-key maps, one per priority.","Validate the shape with the helper above before pushing the config.","Generate the structure from a typed list of {name, config} pairs instead of hand-writing JSON."],"tags":["rls","service-config","config-validation","go","grpc","child-policy"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}