RicoSuter/NSwag · error · InvalidOperationException

The method ' ' on path ' ' is registered multiple times for…

Error message

The method '{operation.Method}' on path '{path}' is registered multiple times for actions {string.Join(", ", conflictingApiDescriptions.Select(apiDesc => apiDesc.ActionDescriptor.DisplayName))}.

What it means

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.

Solutions

  1. Give each colliding action a distinct route template or HTTP method in its attribute routing (e.g. [HttpGet("{id:int}")] vs [HttpGet("active")]).
  2. Remove or merge the duplicate action that is not needed.
  3. Apply [ApiExplorerSettings(IgnoreApi = true)] to the action that should not appear in the document.
  4. 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).

Example fix

// before
[HttpPost]
public IActionResult Create(OrderDto dto) { ... }
[HttpPost]
public IActionResult Update(OrderDto dto) { ... }

// after
[HttpPost("create")]
public IActionResult Create(OrderDto dto) { ... }
[HttpPost("update")]
public IActionResult Update(OrderDto dto) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Before generating, scan API descriptions for (path, method) collisions
var collisions = apiDescriptions
    .GroupBy(d => (d.RelativePath, d.HttpMethod.ToUpperInvariant()))
    .Where(g => g.Count() > 1);
if (collisions.Any())
    throw new InvalidOperationException("Duplicate route/method: " +
        string.Join(", ", collisions.Select(g => g.Key)));

Try / catch

try { var doc = await generator.GenerateAsync(settings); }
catch (InvalidOperationException ex) when (ex.Message.Contains("is registered multiple times"))
{
    logger.LogError(ex, "Duplicate route registration in API actions");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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].

Related errors


AI-assisted analysis of RicoSuter/NSwag@63daf8fcc3 (2026-09-14). Data as JSON: /api/errors/76945480b863359b. Report an issue: GitHub.

Appendix: source

Thrown at src/NSwag.Generation.AspNetCore/AspNetCoreOpenApiDocumentGenerator.cs:344

                    swaggerGenerator,
                    schemaResolver);

                if (addOperation)
                {
                    var path = operation.Path.Replace("//", "/");
                    if (!document.Paths.TryGetValue(path, out var pathItem))
                    {
                        document.Paths[path] = pathItem = [];
                    }

                    if (pathItem.ContainsKey(operation.Method))
                    {
                        var conflictingApiDescriptions = operations
                            .Where(t => t.Item1.Path == operation.Path && t.Item1.Method == operation.Method)
                            .Select(t => t.Item2)
                            .ToList();

                        throw new InvalidOperationException($"The method '{operation.Method}' on path '{path}' is registered multiple times for actions {string.Join(", ", conflictingApiDescriptions.Select(apiDesc => apiDesc.ActionDescriptor.DisplayName))}.");
                    }

                    pathItem[operation.Method] = operation.Operation;
                    addedOperations.Add(tuple);
                }
            }

            return addedOperations;
        }

        private static void UpdateConsumesAndProduces(
            OpenApiDocument document,
            List<Tuple<OpenApiOperationDescription, ApiDescription, MethodInfo>> allOperations)
        {
            // TODO: Move to SwaggerGenerator class?

            var documentConsumes = allOperations
                .SelectMany(s => s.Item1.Operation.Consumes)

View on GitHub (pinned to 63daf8fcc3)