{"record":{"id":"6ea867aaf969fe07","repo":"grpc-ecosystem/grpc-gateway","slug":"duplicate-annotation-method-s-template-s","errorCode":null,"errorMessage":"duplicate annotation: method=%s, template=%s","messagePattern":"duplicate annotation: method=(.+?), template=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/descriptor/registry.go","lineNumber":859,"sourceCode":"}\n\n// GetOpenAPIFieldOption returns a registered OpenAPI option for a field\nfunc (r *Registry) GetOpenAPIFieldOption(qualifiedField string) (*options.JSONSchema, bool) {\n\topt, ok := r.fieldOptions[qualifiedField]\n\treturn opt, ok\n}\n\nfunc (r *Registry) FieldName(f *Field) string {\n\tif r.useJSONNamesForFields {\n\t\treturn f.GetJsonName()\n\t}\n\treturn f.GetName()\n}\n\nfunc (r *Registry) CheckDuplicateAnnotation(httpMethod string, httpTemplate string, svc *Service) error {\n\ta := annotationIdentifier{method: httpMethod, pathTemplate: httpTemplate, service: svc}\n\tif _, ok := r.annotationMap[a]; ok {\n\t\treturn fmt.Errorf(\"duplicate annotation: method=%s, template=%s\", httpMethod, httpTemplate)\n\t}\n\tr.annotationMap[a] = struct{}{}\n\treturn nil\n}\n\n// SetDisableServiceTags sets disableServiceTags\nfunc (r *Registry) SetDisableServiceTags(use bool) {\n\tr.disableServiceTags = use\n}\n\n// GetDisableServiceTags returns disableServiceTags\nfunc (r *Registry) GetDisableServiceTags() bool {\n\treturn r.disableServiceTags\n}\n\n// SetDisableDefaultResponses sets disableDefaultResponses\nfunc (r *Registry) SetDisableDefaultResponses(use bool) {\n\tr.disableDefaultResponses = use","sourceCodeStart":841,"sourceCodeEnd":877,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/internal/descriptor/registry.go#L841-L877","documentation":"CheckDuplicateAnnotation guards against two HTTP rule annotations sharing the same method+path template within a service. Duplicate mappings would generate ambiguous routes, so the registry records each (method, template, service) and errors on re-registration.","triggerScenarios":"A proto service has two rpcs annotated with the same HTTP verb and identical path pattern (e.g. two 'get' rules for '/v1/items'); calling CheckDuplicateAnnotation twice with the same httpMethod/httpTemplate for a service.","commonSituations":"Copy-pasting google.api.http annotations between rpcs and forgetting to change the path; template parameters renamed but base path left identical; merging branches that each added an rpc on the same route.","solutions":["Change the path template of one of the conflicting rpcs to a unique pattern","Differentiate resources via distinct template variables (e.g. '/v1/items/{id}' vs '/v1/items')","Remove the redundant rpc or annotation","Review the service's google.api.http annotations for copy-paste leftovers"],"exampleFix":"// before\nrpc GetBook(...) returns (...) { option (google.api.http) = { get: \"/v1/books/{id}\" }; }\nrpc ListBooks(...) returns (...) { option (google.api.http) = { get: \"/v1/books/{id}\" }; }\n// after\nrpc ListBooks(...) returns (...) { option (google.api.http) = { get: \"/v1/books\" }; }","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, rpc := range svc.Rpcs {\n    key := httpMethod(rpc) + \" \" + pathTemplate(rpc)\n    if seen[key] { return fmt.Errorf(\"duplicate HTTP mapping in service %s: %s\", svc.GetName(), key) }\n    seen[key] = true\n}\nerr = reg.CheckDuplicateAnnotation(method, template, svc)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint google.api.http annotations for duplicate verb+path pairs in CI (buf lint does this)","Never copy an annotation without changing the path template","Design resource paths so every rpc maps to a unique method+URL combination"],"tags":["http-routing","protobuf","annotation","duplicate"],"backgroundTag":"duplicate-route-annotation","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}