{"record":{"id":"e079317ac14cae57","repo":"grpc/grpc-go","slug":"duplicated-name","errorCode":null,"errorMessage":"duplicated name","messagePattern":"duplicated name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"service_config.go","lineNumber":129,"sourceCode":"\t// between 0 and maxTokens.\n\t//\n\t// This field is required and must be greater than zero.\n\tMaxTokens float64\n\t// The amount of tokens to add on each successful RPC. Typically this will\n\t// be some number between 0 and 1, e.g., 0.1.\n\t//\n\t// This field is required and must be greater than zero. Up to 3 decimal\n\t// places are supported.\n\tTokenRatio float64\n}\n\ntype jsonName struct {\n\tService string\n\tMethod  string\n}\n\nvar (\n\terrDuplicatedName             = errors.New(\"duplicated name\")\n\terrEmptyServiceNonEmptyMethod = errors.New(\"cannot combine empty 'service' and non-empty 'method'\")\n)\n\nfunc (j jsonName) generatePath() (string, error) {\n\tif j.Service == \"\" {\n\t\tif j.Method != \"\" {\n\t\t\treturn \"\", errEmptyServiceNonEmptyMethod\n\t\t}\n\t\treturn \"\", nil\n\t}\n\tres := \"/\" + j.Service + \"/\"\n\tif j.Method != \"\" {\n\t\tres += j.Method\n\t}\n\treturn res, nil\n}\n\n// TODO(lyuxuan): delete this struct after cleaning up old service config implementation.","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/service_config.go#L111-L147","documentation":"errDuplicatedName (service_config.go:129) is returned while parsing a service config when two entries in methodConfig[].name[] resolve to the same path. generatePath() builds \"/<service>/<method>\" (or \"/<service>\" for service-wide), and the parser keys MethodConfigs by that path; a duplicate collision at service_config.go:250-251 aborts the parse via serviceconfig.ParseResult.Err. This is a client-side parse error of the service config (from name resolution / default-service-config), not a runtime RPC error.","triggerScenarios":"A service config JSON where methodConfig[].name lists the same {service, method} pair twice, or two methodConfig entries covering the same \"/Service/Method\" path, or two service-wide {\"service\":\"Foo\"} entries that both expand to \"/Foo\". Served via DNS TXT records, xDS, or grpc.WithDefaultServiceConfig.","commonSituations":"Hand-edited service config JSON; copy-paste of method config blocks; service config generation tools emitting overlapping name patterns; upgrading a config that used wildcards now treated as explicit.","solutions":["Inspect the full service config JSON and de-duplicate the methodConfig[].name entries so each /Service/Method (and each /Service) path appears exactly once.","Enable gRPC client logging at WARNING to capture the 'grpc: error unmarshalling service config ... methodConfig[N]' line, which names the offending index.","If the config is fetched from a name resolver (DNS/xDS), correct it at the source; if set via grpc.WithDefaultServiceConfig, fix the embedded string.","Validate the config with a small parser/lint rule that no two names collapse to the same path before deploying."],"exampleFix":"// before\n\"methodConfig\": [\n  { \"name\": [{\"service\":\"foo.Bar\",\"method\":\"Echo\"}], \"timeout\": \"1s\" },\n  { \"name\": [{\"service\":\"foo.Bar\",\"method\":\"Echo\"}], \"retryPolicy\": {...} }\n]\n\n// after\n\"methodConfig\": [\n  { \"name\": [{\"service\":\"foo.Bar\",\"method\":\"Echo\"}], \"timeout\": \"1s\", \"retryPolicy\": {...} }\n]","handlingStrategy":"validation","validationCode":"// Validate a service config for duplicate method paths before installing it.\nfunc validateServiceConfig(cfg string) error {\n    var sc struct {\n        MethodConfig []struct {\n            Name []struct{ Service, Method string } `json:\"name\"`\n        } `json:\"methodConfig\"`\n    }\n    if err := json.Unmarshal([]byte(cfg), &sc); err != nil {\n        return err\n    }\n    seen := map[string]struct{}{}\n    for _, mc := range sc.MethodConfig {\n        for _, n := range mc.Name {\n            path := \"/\" + n.Service + \"/\" + n.Method\n            if n.Method == \"\" {\n                path = \"/\" + n.Service\n            }\n            if _, dup := seen[path]; dup {\n                return fmt.Errorf(\"duplicated name: %s\", path)\n            }\n            seen[path] = struct{}{}\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"pr := serviceconfig.Parse(cfg)\nif pr.Err != nil {\n    if strings.Contains(pr.Err.Error(), \"duplicated name\") {\n        // dedupe the offending methodConfig[].name entries\n    }\n}","preventionTips":["Lint service config JSON so each /Service/Method path appears once.","Generate method config from code/templates rather than hand-editing to avoid overlap.","Enable WARNING logs to catch the 'error unmarshalling service config ... methodConfig[N]' line."],"tags":["grpc","service-config","client","go","config"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}