{"record":{"id":"af2bc199d28fa57d","repo":"grpc/grpc-go","slug":"rls-json-marshal-failed-for-child-policy-config","errorCode":null,"errorMessage":"rls: json marshal failed for child policy config {%+v}: %v","messagePattern":"rls: json marshal failed for child policy config (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/config.go","lineNumber":315,"sourceCode":"\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}\n\treturn d.AsDuration(), d.CheckValid()\n}\n","sourceCodeStart":297,"sourceCodeEnd":331,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/config.go#L297-L331","documentation":"After injecting the dummy target field, RLS marshals the map[string]json.RawMessage back to JSON to hand to the child policy's ParseConfig. Because every value is already valid json.RawMessage and the key is a string, json.Marshal essentially cannot fail; this branch is a defensive guard. Hitting it indicates memory/type corruption or a custom RawMessage containing invalid bytes.","triggerScenarios":"Effectively unreachable in normal operation. Theoretically: a json.RawMessage value in the map that is not valid JSON and confuses the encoder, or an internal panic recovered into an error path.","commonSituations":"Near-impossible via config alone; would only appear with a corrupted in-memory config, a fork that mutated RawMessage fields, or a Go runtime/encoding bug.","solutions":["Treat this as an internal bug: capture the exact config and gRPC-Go version and file an issue.","Re-resolve/redeploy the service config fresh to rule out transient memory corruption.","If running a fork, diff against upstream config.go around line 312-316."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := rlsBB{}.ParseConfig(rawCfg); err != nil {\n    if strings.Contains(err.Error(), \"json marshal failed for child policy config\") {\n        // defensively unreachable; log and fall back to a known-good config\n        logger.Errorw(\"internal RLS marshal failure\", \"err\", err)\n        rawCfg = knownGoodConfig\n    } else {\n        return err\n    }\n}","preventionTips":["Treat this error as an internal bug; report it with the config and gRPC version.","Keep a known-good fallback service config to swap in if parse fails unexpectedly.","Do not fork json.RawMessage handling in config.go."],"tags":["rls","service-config","internal","go","grpc"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}