{"record":{"id":"b76158dbf14ad126","repo":"dotnet/aspnetcore","slug":"the-following-routes-are-ambiguous-existingtext","errorCode":null,"errorMessage":"The following routes are ambiguous:\n'{existingText}' in '{existing.Handler.FullName}'\n'{currentText}' in '{current.Handler.FullName}'\n","messagePattern":"The following routes are ambiguous:\n'(.+?)' in '(.+?)'\n'(.+?)' in '(.+?)'\n","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Routing/RouteTableFactory.cs","lineNumber":214,"sourceCode":"            RoutePattern = parsedTemplate,\n            UnusedRouteParameterNames = GetUnusedParameterNames(result.AllRouteParameterNames, routeParameterNames!),\n        };\n    }\n    private static void DetectAmbiguousRoutes(TreeRouteBuilder builder)\n    {\n        var seen = new HashSet<InboundRouteEntry>(new InboundRouteEntryAmbiguityEqualityComparer());\n        seen.EnsureCapacity(builder.InboundEntries.Count);\n\n        for (var i = 0; i < builder.InboundEntries.Count; i++)\n        {\n            var current = builder.InboundEntries[i];\n\n            if (!seen.Add(current))\n            {\n                seen.TryGetValue(current, out var existing);\n                var existingText = existing!.RoutePattern.RawText!.Trim('/');\n                var currentText = current.RoutePattern.RawText!.Trim('/');\n                throw new InvalidOperationException($\"\"\"\n                    The following routes are ambiguous:\n                    '{existingText}' in '{existing.Handler.FullName}'\n                    '{currentText}' in '{current.Handler.FullName}'\n\n                    \"\"\");\n            }\n        }\n    }\n\n    private static HashSet<string> GetParameterNames(RoutePattern routeTemplate)\n    {\n        var parameterNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n        foreach (var parameter in routeTemplate.Parameters)\n        {\n            parameterNames.Add(parameter.Name!);\n        }\n\n        return parameterNames;","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/Routing/RouteTableFactory.cs#L196-L232","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"<!-- before: Component A -->\n@page \"/users\"\n<!-- before: Component B -->\n@page \"/users\"\n\n<!-- after -->\n@page \"/users\"      <!-- Component A -->\n@page \"/users/list\" <!-- Component B -->","handlingStrategy":"validation","validationCode":"// At startup/test, scan all @page templates across the Router's assemblies for duplicates.\nstatic IEnumerable<string> DuplicateRoutes(params Assembly[] assemblies) =>\n    assemblies.SelectMany(a => a.GetTypes())\n        .SelectMany(t => t.GetCustomAttributes(typeof(RouteAttribute), true)\n            .Cast<RouteAttribute>().Select(ra => ra.Template?.TrimEnd('/')))\n        .GroupBy(r => r, StringComparer.OrdinalIgnoreCase)\n        .Where(g => g.Count() > 1).Select(g => g.Key);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["blazor","routing","ambiguous-routes","duplicate-route","configuration"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}