{"record":{"id":"76945480b863359b","repo":"RicoSuter/NSwag","slug":"the-method-operation-method-on-path-path-is-registered","errorCode":null,"errorMessage":"The method '{operation.Method}' on path '{path}' is registered multiple times for actions {string.Join(\", \", conflictingApiDescriptions.Select(apiDesc => apiDesc.ActionDescriptor.DisplayName))}.","messagePattern":"The method '(.+?)' on path '(.+?)' is registered multiple times for actions (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/NSwag.Generation.AspNetCore/AspNetCoreOpenApiDocumentGenerator.cs","lineNumber":344,"sourceCode":"                    swaggerGenerator,\n                    schemaResolver);\n\n                if (addOperation)\n                {\n                    var path = operation.Path.Replace(\"//\", \"/\");\n                    if (!document.Paths.TryGetValue(path, out var pathItem))\n                    {\n                        document.Paths[path] = pathItem = [];\n                    }\n\n                    if (pathItem.ContainsKey(operation.Method))\n                    {\n                        var conflictingApiDescriptions = operations\n                            .Where(t => t.Item1.Path == operation.Path && t.Item1.Method == operation.Method)\n                            .Select(t => t.Item2)\n                            .ToList();\n\n                        throw new InvalidOperationException($\"The method '{operation.Method}' on path '{path}' is registered multiple times for actions {string.Join(\", \", conflictingApiDescriptions.Select(apiDesc => apiDesc.ActionDescriptor.DisplayName))}.\");\n                    }\n\n                    pathItem[operation.Method] = operation.Operation;\n                    addedOperations.Add(tuple);\n                }\n            }\n\n            return addedOperations;\n        }\n\n        private static void UpdateConsumesAndProduces(\n            OpenApiDocument document,\n            List<Tuple<OpenApiOperationDescription, ApiDescription, MethodInfo>> allOperations)\n        {\n            // TODO: Move to SwaggerGenerator class?\n\n            var documentConsumes = allOperations\n                .SelectMany(s => s.Item1.Operation.Consumes)","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/RicoSuter/NSwag/blob/63daf8fcc3a25151b62eb4b326a1e8ea048a0d41/src/NSwag.Generation.AspNetCore/AspNetCoreOpenApiDocumentGenerator.cs#L326-L362","documentation":"NSwag's ASP.NET Core generator refuses to build the document when two API descriptions resolve to the same HTTP method and route path, because a single OpenAPI path item can only hold one operation per method. In AddOperationDescriptionsToDocument, after adding an operation it checks whether another action already produced the same (path, method) tuple and throws InvalidOperationException listing the conflicting action DisplayNames. This usually means two controller actions are indistinguishable by route.","triggerScenarios":"Calling GenerateControllers/UseHttpRepl-style document generation (AddOpenApiDocument/AddSwaggerDocument with an IApiDescriptionGroupCollectionProvider) when two actions map to the same path template and HTTP method, e.g. two [HttpPost(\"save\")] actions in the same controller, or attribute routing that collapses two actions onto one route.","commonSituations":"Overloaded action methods without distinct [HttpGet(\"...\")] templates; a route-template typo making two actions match; adding a new controller action that collides with an existing one; using conventional routing where DefaultUrlTemplate maps two actions to the same path; duplicated controllers registered with different namespaces but the same [Route].","solutions":["Give each colliding action a distinct route template or HTTP method in its attribute routing (e.g. [HttpGet(\"{id:int}\")] vs [HttpGet(\"active\")]).","Remove or merge the duplicate action that is not needed.","Apply [ApiExplorerSettings(IgnoreApi = true)] to the action that should not appear in the document.","Check the DisplayName values in the message to locate the exact conflicting controller actions and disambiguate their constraints (route constraints, HTTP method, accepted content type)."],"exampleFix":"// before\n[HttpPost]\npublic IActionResult Create(OrderDto dto) { ... }\n[HttpPost]\npublic IActionResult Update(OrderDto dto) { ... }\n\n// after\n[HttpPost(\"create\")]\npublic IActionResult Create(OrderDto dto) { ... }\n[HttpPost(\"update\")]\npublic IActionResult Update(OrderDto dto) { ... }","handlingStrategy":"validation","validationCode":"// Before generating, scan API descriptions for (path, method) collisions\nvar collisions = apiDescriptions\n    .GroupBy(d => (d.RelativePath, d.HttpMethod.ToUpperInvariant()))\n    .Where(g => g.Count() > 1);\nif (collisions.Any())\n    throw new InvalidOperationException(\"Duplicate route/method: \" +\n        string.Join(\", \", collisions.Select(g => g.Key)));","typeGuard":null,"tryCatchPattern":"try { var doc = await generator.GenerateAsync(settings); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"is registered multiple times\"))\n{\n    logger.LogError(ex, \"Duplicate route registration in API actions\");\n}","preventionTips":["Give every action a unique (route template, HTTP method) pair; use route constraints to disambiguate.","Run document generation in CI/tests so collisions fail the build early.","Use [ApiExplorerSettings(IgnoreApi = true)] deliberately to exclude helper actions."],"tags":["aspnetcore","swagger","routing","openapi"],"backgroundTag":"duplicate-route-registration","analyzedSha":"63daf8fcc3a25151b62eb4b326a1e8ea048a0d41","analyzedAt":"2026-09-14T11:38:15.205Z","contentChangedAt":"2026-09-14T11:38:15.205Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}