Skip to content

go_router_builder: TypedRelativeRoute always uses root route #182441

@Mikkelet

Description

@Mikkelet

Steps to reproduce

dependencies

environment:
  sdk: ^3.9.2
dependencies:
  flutter:
    sdk: flutter
  go_router: ^17.1.0

dev_dependencies:
  build_runner: ^2.6.0
  go_router_builder: ^4.0.1
  1. create 3 routes: 2 Typed, 1 Relative
  2. add a print statement to go-router redirect: print("uri=${state.uri});
  3. add the relative route to both other routes
  4. add navigation from routeA to routeB eg. RouteB().push(context)
  5. add navigation from routeA to relativeRoute eg. RelativeRouteA().pushRelative(context)
  6. add navigation from routeB to relativeRoute eg. RelativeRouteA().pushRelative(context)
  7. start app
  8. navigate from routeA to routeB
  9. navigate to relativeRoute
  10. notice that the printed uri is /routeA/relativeRoute and not /routeB/relativeRoute as I would expect

Expected results

I expect to be navigated to /currentRoute/relativeRoute

Actual results

I get navigated to /rootRoute/relativeRoute

Code sample

GoRouter router.dart
import 'package:go_router/go_router.dart';
import 'package:go_router_sandbox/navigation/app_routes.dart';

abstract class AppRoutes {
  static const home = "/home";
  static const products = "/products";
  static const product = "/products/:id";

  // relative routes
  static const reviews = "reviews";
}

final router = GoRouter(
  initialLocation: AppRoutes.home,
  redirect: (context, state) {
    print("qqq uri=${state.uri}");
    return null;
  },
  routes: $appRoutes,
);

routes.dart

import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart';
import 'package:go_router_sandbox/screens/home/home_screen.dart';
import 'package:go_router_sandbox/screens/product/product_screen.dart';
import 'package:go_router_sandbox/screens/products_list/products_list_screen.dart';
import 'package:go_router_sandbox/screens/reviews/reviews_list_screen.dart';

import 'app_router.dart';

part 'app_routes.g.dart';

@TypedGoRoute<HomeRoute>(
  path: AppRoutes.home,
  routes: [
    TypedRelativeGoRoute<ReviewsRoute>(path: AppRoutes.reviews),
  ],
)
class HomeRoute extends GoRouteData with $HomeRoute {
  @override
  Widget build(BuildContext context, GoRouterState state) {
    return HomeScreen();
  }
}

@TypedGoRoute<ProductRoute>(
  path: AppRoutes.product,
  routes: [
    TypedRelativeGoRoute<ReviewsRoute>(path: AppRoutes.reviews),
  ],
)
class ProductRoute extends GoRouteData with $ProductRoute {
  final int id;

  const ProductRoute(this.id);

  @override
  Widget build(BuildContext context, GoRouterState state) {
    return ProductScreen(id: id);
  }
}

@TypedGoRoute<ProductsListRoute>(
  path: AppRoutes.products,
  routes: [
    TypedRelativeGoRoute<ReviewsRoute>(path: AppRoutes.reviews),
  ],
)
class ProductsListRoute extends GoRouteData with $ProductsListRoute {
  @override
  Widget build(BuildContext context, GoRouterState state) {
    return ProductsListScreen();
  }
}

@TypedRelativeGoRoute<ReviewsRoute>(path: AppRoutes.reviews, routes: [])
class ReviewsRoute extends RelativeGoRouteData with $ReviewsRoute {
  @override
  Widget build(BuildContext context, GoRouterState state) {
    return ReviewsListScreen();
  }
}
Screens home_screen.dart
import 'package:flutter/material.dart';
import 'package:go_router_sandbox/navigation/app_routes.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text("HomeScreen"),
            TextButton(
              onPressed: () {
                ProductsListRoute().push(context);
              },
              child: Text("Push /products"),
            ),
            TextButton(
              onPressed: () {
                ReviewsRoute().pushRelative(context);
              },
              child: Text("Push /home/reviews"),
            ),
          ],
        ),
      ),
    );
  }
}

product_screens.g.dart

import 'package:flutter/material.dart';
import 'package:go_router_sandbox/navigation/app_routes.dart';

class ProductScreen extends StatelessWidget {
  const ProductScreen({super.key, required this.id});

  final int id;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text("PRODUCT :$id"),
            TextButton(
              onPressed: () {
                ReviewsRoute().pushRelative(context);
              },
              child: Text("Push /products/$id/reviews"),
            ),
          ],
        ),
      ),
    );
  }
}

products_list.darg

import 'package:flutter/material.dart';
import '../../navigation/app_routes.dart';

class ProductsListScreen extends StatelessWidget {
  const ProductsListScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text("PRODUCTS"),
            ...List.generate(10, (i) => i).map((id) {
              return TextButton(
                onPressed: () {
                  ProductRoute(id).push(context);
                },
                child: Text("Product $id"),
              );
            }),
            TextButton(
              onPressed: () {
                ReviewsRoute().pushRelative(context);
              },
              child: Text("Push /products/reviews"),
            ),
          ],
        ),
      ),
    );
  }
}

reviews.dart

import 'package:flutter/material.dart';

class ReviewsListScreen extends StatelessWidget {
  const ReviewsListScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text("REVIEWS"),
            ...List.generate(10, (i) => i).map((id) {
              return TextButton(
                onPressed: () {},
                child: Text("Review $id"),
              );
            }),
          ],
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
18:03:02.780  I  uri=/home
18:03:05.988  I  uri=/home/reviews 
// back nav

18:03:10.238  I  uri=/products
18:03:12.311  I  uri=/home/reviews
// back nav

18:03:15.954  I  uri=/products/9
18:03:17.020  I  uri=/home/reviews

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.35.6, on macOS 26.2 25C56 darwin-arm64, locale en-US) [977ms]
    • Flutter version 3.35.6 on channel stable at /Users/mth/fvm/versions/3.35.6
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 9f455d2486 (4 months ago), 2025-10-08 14:55:31 -0500
    • Engine revision d2913632a4
    • Dart version 3.9.2
    • DevTools version 2.48.0
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-swift-package-manager, enable-lldb-debugging

[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0) [2.6s]
    • Android SDK at /Users/mth/Library/Android/sdk
    • Emulator version 36.2.12.0 (build_id 14214601) (CL:N/A)
    • Platform android-36, build-tools 36.1.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.8+-14196175-b1038.72)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 26.2) [1,526ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 17C52
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [6ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2025.2) [6ms]
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.8+-14196175-b1038.72)

[✓] VS Code (version 1.109.0) [5ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (4 available) [9.5s]
    • sdk gphone64 arm64 (mobile)                • emulator-5554             • android-arm64  • Android 16 (API 36) (emulator)
    • macOS (desktop)                            • macos                     • darwin-arm64   • macOS 26.2 25C56 darwin-arm64
    • Chrome (web)                               • chrome                    • web-javascript • Google Chrome 144.0.7559.135

[✓] Network resources [608ms]
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listhas reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: go_router_builderThe go_router_builder packagepackageflutter/packages repository. See also p: labels.team-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions