dotnet/aspnetcore · error · InvalidOperationException
The following routes are ambiguous: '{existingText}' in '{ex
Error message
The following routes are ambiguous:
'{existingText}' in '{existing.Handler.FullName}'
'{currentText}' in '{current.Handler.FullName}'
What it means
Thrown by RouteTableFactory.DetectAmbiguousRoutes when two InboundRouteEntry entries are equal under InboundRouteEntryAmbiguityEqualityComparer (same route pattern). The router disallows two components resolving the same URL because it could not pick one deterministically, so the conflict is reported at route-table build time.
Source
Thrown at src/Components/Components/src/Routing/RouteTableFactory.cs:214
RoutePattern = parsedTemplate,
UnusedRouteParameterNames = GetUnusedParameterNames(result.AllRouteParameterNames, routeParameterNames!),
};
}
private static void DetectAmbiguousRoutes(TreeRouteBuilder builder)
{
var seen = new HashSet<InboundRouteEntry>(new InboundRouteEntryAmbiguityEqualityComparer());
seen.EnsureCapacity(builder.InboundEntries.Count);
for (var i = 0; i < builder.InboundEntries.Count; i++)
{
var current = builder.InboundEntries[i];
if (!seen.Add(current))
{
seen.TryGetValue(current, out var existing);
var existingText = existing!.RoutePattern.RawText!.Trim('/');
var currentText = current.RoutePattern.RawText!.Trim('/');
throw new InvalidOperationException($"""
The following routes are ambiguous:
'{existingText}' in '{existing.Handler.FullName}'
'{currentText}' in '{current.Handler.FullName}'
""");
}
}
}
private static HashSet<string> GetParameterNames(RoutePattern routeTemplate)
{
var parameterNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var parameter in routeTemplate.Parameters)
{
parameterNames.Add(parameter.Name!);
}
return parameterNames;View on GitHub (pinned to 294cab2f9b)
Solutions
- Search all @page directives in the solution for the duplicated template (the message names both conflicting components).
- Change one component's @page template so the routes differ.
- If one definition is obsolete, remove the [Route]/@page from it or exclude the assembly from the Router's AppAssembly/AdditionalAssemblies.
Example fix
<!-- before: Component A --> @page "/users" <!-- before: Component B --> @page "/users" <!-- after --> @page "/users" <!-- Component A --> @page "/users/list" <!-- Component B -->
Defensive patterns
Strategy: validation
Validate before calling
// At startup/test, scan all @page templates across the Router's assemblies for duplicates.
static IEnumerable<string> DuplicateRoutes(params Assembly[] assemblies) =>
assemblies.SelectMany(a => a.GetTypes())
.SelectMany(t => t.GetCustomAttributes(typeof(RouteAttribute), true)
.Cast<RouteAttribute>().Select(ra => ra.Template?.TrimEnd('/')))
.GroupBy(r => r, StringComparer.OrdinalIgnoreCase)
.Where(g => g.Count() > 1).Select(g => g.Key); Prevention
- Search the codebase for repeated @page templates before adding a new one.
- When splitting pages across assemblies (AdditionalAssemblies), check both for overlap.
- Add a test that asserts no duplicate route templates exist in the scanned assemblies.
When it happens
Trigger: Two components in the scanned assemblies declare @page "/same/path" (identical template). Fires when the Router builds its route table on first navigation, scanning AppAssembly (+ AdditionalAssemblies).
Common situations: Copy-pasting a page and forgetting to change its @page; two assemblies in AdditionalAssemblies both defining the same route; a shared library and the app both declaring a route; case-only differences that the equality comparer treats as duplicates.
Related errors
- The Router component requires a value for the parameter AppA
- The Router component requires a value for the parameter Foun
- Setting NotFound and NotFoundPage properties simultaneously
- The type {NotFoundPage.FullName} does not have a Microsoft.A
- EqualTo validator requires a non-empty "other" parameter.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/b76158dbf14ad126.
Report an issue: GitHub.