Skip to content

[go_router_builder] Report duplicate route paths at build time #190741

Closed
flutter/packages
#12399

Description

@brianegan

Use case

As a developer

  • Given I declare two separate routes with the same path
  • When, I run go_router_builder
  • Then, I want to know about my mistake at build time so I can fix it. Otherwise, I run into unexpected behavior at runtime.

Current behavior

First declared wins, but not always. I tested all three cases against go_router 17.3.0.

Duplicate leaf paths: the first wins, the second is dead. Configuration._getLocRouteMatches walks the root routes in declaration order and returns the first non-empty result (configuration.dart:395-405). Children do the same and break on the first hit (match.dart:264-277). Two details leaves under /home, and /home/details renders the first.

Paths differing only in parameter name: same, first wins. /meal/:id before /meal/:mealId, navigating to /meal/7 renders the first and populates id with 7. The second builder never runs, so mealId is never read. A failed attempt doesn't leak parameters either, since each route stages them in a temp map and merges only once it's part of the result (match.dart:216-225).

Duplicate paths with different children: the second is reachable. This is the one that breaks the simple story. Matching backtracks. A route that matches a prefix but whose children can't complete the URL returns empty (match.dart:278-282), and the sibling loop keeps going. So with:

/home
  details -> [a]
  details -> [b]

/home/details/b reaches child b through the second details. I confirmed it renders. /home/details on its own still resolves to the first.

Proposal

  • Detect the conflict in go_router_builder and report it at build time. Two routes conflict when they compete for the same URL namespace and their paths normalize to the same pattern, so meal/:id and meal/:mealId count as one pattern.
  • Resolve namespaces per level of the route tree. Shell routes and StatefulShellRoute branches own no path, so the routes inside them compete with the routes around them. Relative routes own their path like any other route. Separate annotations compete, since $appRoutes collects them into one list. A library includes its part files, which covers an app's whole route table given it has to live in one library today ([go_router_builder] Define routes in separate files #122258).
  • Report rather than fail, by default. The third case above works at runtime, because matching backtracks, so a hard error would fail the build of an app that runs correctly. Same for one route class declared twice with different children, which is a way to group children by feature area. Every route still generates and the author decides what to do.
  • Make the severity configurable with a duplicate_route_paths builder option, accepting warning (the default), error, and ignore. Teams whose duplicates are always mistakes get a hard failure, and teams using the grouping pattern set ignore. Package-wide, with no per-route escape hatch.
  • Worth noting the check has already earned its keep: go_router_builder's own example app registered DoubleRoute twice since [go_router_builder] Adds support for enhanced enums. packages#2395 (2022) and DoubleExtensionRoute twice since [go_router_builder] Support extension types packages#9458 (2025). Both duplicates were unreachable, and removing them changed nothing but the dead entries in the generated route list.

Activity

  1. added
    packageflutter/packages repository. See also p: labels.
    c: proposalA detailed proposal for a change to Flutter
    on Aug 10, 2026
  2. added a commit that references this issue on Sep 2, 2026
    0099ae1
  3. added 2 commits that reference this issue on Sep 9, 2026
    845b72b
    49dfa69
  4. github-actions commented on Sep 16, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  5. locked as resolved and limited conversation to collaborators on Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projecta: error messageError messages from the Flutter frameworkc: proposalA detailed proposal for a change to Flutterp: go_router_builderThe go_router_builder packagepackageflutter/packages repository. See also p: labels.team-ecosystemOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamwaiting for PR to land (fixed)A fix is in flight

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions