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 action {string.Join(", ", conflictingOperationDisplayNames)} (check the DefaultUrlTemplate setting [default for Web API: 'api/{controller}/{id}'; for MVC projects: '{controller}/{action}/{id?}']). What it means
The WebApi generator's AddOperationDescriptionsToDocument (called from GenerateForController) throws InvalidOperationException when two operations on a controller resolve to the same path and HTTP method under the configured DefaultUrlTemplate, since an OpenAPI path item allows one operation per method. The message also hints that the DefaultUrlTemplate setting (default 'api/{controller}/{id}' for Web API, '{controller}/{action}/{id?}' for MVC) may be causing the collision.
Solutions
- Check/fix the DefaultUrlTemplate setting so paths differ per action (e.g. use '{controller}/{action}/{id?}' for MVC-style controllers).
- Give each colliding action a distinct route template ([Route] / [HttpPost("...")]) or HTTP method.
- Remove or merge the duplicate action, or hide it from the document.
- Use the action names listed in the message (GetDisplayName output) to locate the exact conflicting methods.
Example fix
// before (config)
settings.DefaultUrlTemplate = "api/{controller}/{id}"; // all POST actions collide
// after (config)
settings.DefaultUrlTemplate = "api/{controller}/{action}/{id?}"; Defensive patterns
Strategy: validation
Validate before calling
// Ensure the URL template distinguishes actions before generating
var template = settings.DefaultUrlTemplate;
bool distinguishesActions = template.Contains("{action}") ||
controllerActions.GroupBy(a => ResolvePath(template, a)).All(g => g.Count() == 1); Try / catch
try { document = generator.GenerateForControllers(controllerTypes); }
catch (InvalidOperationException ex) when (ex.Message.Contains("is registered multiple times"))
{
logger.LogError(ex, "Duplicate path/method under DefaultUrlTemplate {Template}", settings.DefaultUrlTemplate);
} Prevention
- Match DefaultUrlTemplate to your routing style ('{controller}/{action}/{id?}' for MVC-style controllers).
- Avoid overloading actions without distinct route attributes.
- Regenerate the document in CI after adding actions so collisions surface immediately.
When it happens
Trigger: Running GenerateForControllers/WebApiOpenApiDocumentGenerator when two actions on a controller produce identical (path, method) tuples — e.g. two POST actions with no route template, or a custom DefaultUrlTemplate that drops the {action} segment so all actions share one path.
Common situations: Setting DefaultUrlTemplate to 'api/{controller}/{id}' while the controller has multiple actions of the same HTTP method; overloading actions without route attributes; copy-pasted actions; switching between Web API and MVC templates without adjusting route templates.
Related errors
- The method ' ' on path ' ' is registered multiple times for…
- The operation ' ' has more than one body parameter.
- NSwag requires the assembly
- The operation ' ' has more than one body parameter.
- does not implement property 'Template
AI-assisted analysis of RicoSuter/NSwag@63daf8fcc3 (2026-09-14).
Data as JSON: /api/errors/eac7297e72098a0d.
Report an issue: GitHub.
Appendix: source
Thrown at src/NSwag.Generation.WebApi/WebApiOpenApiDocumentGenerator.cs:230
var addOperation = RunOperationProcessors(document, controllerType, method, operation, allOperation, swaggerGenerator, schemaResolver);
if (addOperation)
{
var path = operation.Path.Replace("//", "/");
if (!document.Paths.TryGetValue(path, out var pathItem))
{
pathItem = [];
document.Paths[path] = pathItem;
}
if (pathItem.ContainsKey(operation.Method))
{
var conflictingOperationDisplayNames = operations
.Where(t => t.Item1.Path == operation.Path && t.Item1.Method == operation.Method)
.Select(t => GetDisplayName(controllerType, t.Item2))
.ToList();
throw new InvalidOperationException($"The method '{operation.Method}' on path '{path}' is registered multiple times for action {string.Join(", ", conflictingOperationDisplayNames)} " +
"(check the DefaultUrlTemplate setting [default for Web API: 'api/{controller}/{id}'; for MVC projects: '{controller}/{action}/{id?}']).");
}
pathItem[operation.Method] = operation.Operation;
addedOperations++;
}
}
return addedOperations > 0;
}
private static string GetDisplayName(Type controllerType, MethodInfo method)
{
return $"{controllerType.FullName}.{method.Name} ({controllerType.Assembly.GetName().Name})";
}
private bool RunOperationProcessors(OpenApiDocument document, Type controllerType, MethodInfo methodInfo, OpenApiOperationDescription operationDescription,
List<OpenApiOperationDescription> allOperations, OpenApiDocumentGenerator generator, OpenApiSchemaResolver schemaResolver)View on GitHub (pinned to 63daf8fcc3)