What package does this bug report belong to?
go_router
What target platforms are you seeing this bug on?
Android, iOS, Web, macOS, Linux, Windows
Have you already upgraded your packages?
Yes
Dependency versions
pubspec.lock
go_router 17.3.0
(also reproduced against packages/go_router at flutter/packages main, 9e58c600b0)
Steps to reproduce
- Create a
GoRouter with an onEnter callback that returns Block.stop() for the initial location, and provide an onException handler.
- Start the app (any platform — this is pure routing logic; we originally hit it with deep links on web).
The crash happens during setInitialRoutePath, so the app crashes on startup.
Expected results
No crash. onException runs and the app can recover (show an error state or navigate elsewhere).
Actual results
Assertion failure in GoRouterDelegate.setNewRoutePath:
'package:go_router/src/delegate.dart': Failed assertion: line 221 pos 12:
'configuration.isNotEmpty || configuration.isError': is not true.
Cause: when onException is provided, the parserExceptionHandler closure in router.dart always returns routerDelegate.currentConfiguration. On the initial navigation nothing has committed yet, so that configuration is empty (isNotEmpty == false, isError == false) and the delegate assertion fires. The fix (flutter/packages#12216) has two parts. router.dart falls back to the error match list when the current configuration isn't valid yet — the error list has isError == true, so the assertion is satisfied. We've been running this half in a fork in production. And parser.dart defers the onException invocation past the in-flight initial parse for the blocked-with-no-prior-route case: without that, a recovery navigation made synchronously inside onException (like the router.go('/fallback') above) is silently discarded by the Router's intent-token churn, and the app stays parked on the error state instead of recovering.
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
void main() => runApp(App());
class App extends StatelessWidget {
App({super.key});
late final GoRouter router = GoRouter(
initialLocation: '/protected',
onEnter: (_, __, next, ___) =>
next.matchedLocation == '/protected' ? const Block.stop() : const Allow(),
onException: (context, state, router) => router.go('/fallback'),
routes: [
GoRoute(path: '/protected', builder: (_, __) => const SizedBox()),
GoRoute(path: '/fallback', builder: (_, __) => const SizedBox()),
],
);
@override
Widget build(BuildContext context) => MaterialApp.router(routerConfig: router);
}
Screenshots or Videos
Screenshots / Video demonstration
N/A (startup crash).
Logs
Logs
'package:go_router/src/delegate.dart': Failed assertion: line 221 pos 12:
'configuration.isNotEmpty || configuration.isError': is not true.
#2 GoRouterDelegate.setNewRoutePath (package:go_router/src/delegate.dart:221:12)
#3 RouterDelegate.setInitialRoutePath (package:flutter/src/widgets/router.dart:1358:12)
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.44.4, on macOS 26.5.2 25F84 darwin-arm64, locale en-US) [609ms]
• Flutter version 3.44.4 on channel stable at ~/repos/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision ad70ec4617 (3 weeks ago), 2026-06-24 11:07:06 -0700
• Engine revision a10d8ac38d
• Dart version 3.12.2
• DevTools version 2.57.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [1,824ms]
• Android SDK at ~/Library/Android/sdk
• Emulator version unknown
• Platform android-36, build-tools 36.0.0
• ANDROID_HOME = ~/Library/Android/sdk
• 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.6+-13391695-b895.109)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 26.6) [1,335ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 17F113
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web [6ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Connected device (2 available) [6.8s]
• macOS (desktop) • macos • darwin-arm64 • macOS 26.5.2 25F84 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 150.0.7871.116
[✓] Network resources [789ms]
• All expected network resources are available.
• No issues found!
What package does this bug report belong to?
go_router
What target platforms are you seeing this bug on?
Android, iOS, Web, macOS, Linux, Windows
Have you already upgraded your packages?
Yes
Dependency versions
pubspec.lock
Steps to reproduce
GoRouterwith anonEntercallback that returnsBlock.stop()for the initial location, and provide anonExceptionhandler.The crash happens during
setInitialRoutePath, so the app crashes on startup.Expected results
No crash.
onExceptionruns and the app can recover (show an error state or navigate elsewhere).Actual results
Assertion failure in
GoRouterDelegate.setNewRoutePath:Cause: when
onExceptionis provided, theparserExceptionHandlerclosure inrouter.dartalways returnsrouterDelegate.currentConfiguration. On the initial navigation nothing has committed yet, so that configuration is empty (isNotEmpty == false,isError == false) and the delegate assertion fires. The fix (flutter/packages#12216) has two parts.router.dartfalls back to the error match list when the current configuration isn't valid yet — the error list hasisError == true, so the assertion is satisfied. We've been running this half in a fork in production. Andparser.dartdefers theonExceptioninvocation past the in-flight initial parse for the blocked-with-no-prior-route case: without that, a recovery navigation made synchronously insideonException(like therouter.go('/fallback')above) is silently discarded by theRouter's intent-token churn, and the app stays parked on the error state instead of recovering.Code sample
Code sample
Screenshots or Videos
Screenshots / Video demonstration
N/A (startup crash).
Logs
Logs
Flutter Doctor output
Doctor output