From 7aaae9769eacd4c50e867097aa13792301639b64 Mon Sep 17 00:00:00 2001 From: abhaysaqi Date: Tue, 16 Jun 2026 12:15:53 +0530 Subject: [PATCH 1/4] Fix: guard empty matches in _findCurrentNavigators and popRoute When currentConfiguration.matches is empty (e.g. during startup before first route resolves), calling popRoute() crashed with 'Bad state: No element' from matches.last. Added the same isEmpty guard that canPop() already uses, in both _findCurrentNavigators() and the popRoute() onExit fallback. Fixes #187616 --- packages/go_router/lib/src/delegate.dart | 8 ++++++-- packages/go_router/test/delegate_test.dart | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index 1459d2f395ce..39134f071e46 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -61,7 +61,9 @@ class GoRouterDelegate extends RouterDelegate with ChangeNotifie return true; // Return true if maybePop handled the pop } } - + if (currentConfiguration.matches.isEmpty) { + return false; + } // Fallback to onExit if maybePop did not handle the pop final GoRoute lastRoute = currentConfiguration.last.route; if (lastRoute.onExit != null && navigatorKey.currentContext != null) { @@ -115,7 +117,9 @@ class GoRouterDelegate extends RouterDelegate with ChangeNotifie // Set state directly without canPop check states.add(navigatorKey.currentState!); } - + if (currentConfiguration.matches.isEmpty) { + return states.reversed; + } RouteMatchBase walker = currentConfiguration.matches.last; while (walker is ShellRouteMatch) { final NavigatorState potentialCandidate = walker.navigatorKey.currentState!; diff --git a/packages/go_router/test/delegate_test.dart b/packages/go_router/test/delegate_test.dart index 12d2d914ad6a..98cf1e87b1f6 100644 --- a/packages/go_router/test/delegate_test.dart +++ b/packages/go_router/test/delegate_test.dart @@ -345,6 +345,23 @@ void main() { }); }); + testWidgets('popRoute does not throw Bad state when currentConfiguration is empty', ( + WidgetTester tester, + ) async { + final GoRouter goRouter = GoRouter( + initialLocation: '/', + routes: [GoRoute(path: '/', builder: (_, _) => const DummyStatefulWidget())], + ); + addTearDown(goRouter.dispose); + await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); + + // Simulate empty configuration (e.g. startup window before first route resolves) + goRouter.routerDelegate.currentConfiguration = RouteMatchList.empty; + + // Should return false without throwing "Bad state: No element" + expect(await goRouter.routerDelegate.popRoute(), isFalse); + }); + group('push', () { testWidgets('It should return different pageKey when push is called', ( WidgetTester tester, From 6530be3f800cfafa374247c94f059ca390b5eb3f Mon Sep 17 00:00:00 2001 From: abhaysaqi Date: Tue, 16 Jun 2026 12:27:19 +0530 Subject: [PATCH 2/4] Fix: use currentConfiguration.isEmpty instead of currentConfiguration.matches.isEmpty Use more idiomatic `currentConfiguration.isEmpty` consistent with other parts of the codebase such as `currentConfiguration.isNotEmpty` instead of accessing `matches.isEmpty` directly. --- packages/go_router/lib/src/delegate.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index 39134f071e46..eb9d7325c891 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -61,7 +61,7 @@ class GoRouterDelegate extends RouterDelegate with ChangeNotifie return true; // Return true if maybePop handled the pop } } - if (currentConfiguration.matches.isEmpty) { + if (currentConfiguration.isEmpty) { return false; } // Fallback to onExit if maybePop did not handle the pop @@ -81,7 +81,7 @@ class GoRouterDelegate extends RouterDelegate with ChangeNotifie if (navigatorKey.currentState?.canPop() ?? false) { return true; } - if (currentConfiguration.matches.isEmpty) { + if (currentConfiguration.isEmpty) { return false; } RouteMatchBase walker = currentConfiguration.matches.last; From bd1dca7caebc8fac8e669ce4a4eaa07cfadb7afc Mon Sep 17 00:00:00 2001 From: Abhay <126308813+abhaysaqi@users.noreply.github.com> Date: Tue, 16 Jun 2026 20:16:24 +0530 Subject: [PATCH 3/4] Update packages/go_router/lib/src/delegate.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- packages/go_router/lib/src/delegate.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index eb9d7325c891..ee017c799f77 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -117,7 +117,7 @@ class GoRouterDelegate extends RouterDelegate with ChangeNotifie // Set state directly without canPop check states.add(navigatorKey.currentState!); } - if (currentConfiguration.matches.isEmpty) { + if (currentConfiguration.isEmpty) { return states.reversed; } RouteMatchBase walker = currentConfiguration.matches.last; From d5b6e1264f4c052dd622ee2325aa987f25e2564d Mon Sep 17 00:00:00 2001 From: abhaysaqi Date: Thu, 18 Jun 2026 10:46:47 +0530 Subject: [PATCH 4/4] [go_router] Update version to 17.3.1 and add CHANGELOG entry --- packages/go_router/CHANGELOG.md | 6 ++++++ packages/go_router/pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index 79eb13d61fad..6752386addb0 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,9 @@ +## 17.3.1 + +- Fixes `popRoute()` crashing with `Bad state: No element` when + `currentConfiguration` is empty (e.g. during app startup before + the first route resolves). + ## 17.3.0 - Updates minimum supported SDK version to Flutter 3.38/Dart 3.10. diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index 77e1c11fde77..002dada9f39d 100644 --- a/packages/go_router/pubspec.yaml +++ b/packages/go_router/pubspec.yaml @@ -1,7 +1,7 @@ name: go_router description: A declarative router for Flutter based on Navigation 2 supporting deep linking, data-driven routes and more -version: 17.3.0 +version: 17.3.1 repository: https://github.com/flutter/packages/tree/main/packages/go_router issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22