Skip to content

[go_router] Assertion failure in setNewRoutePath when onException fires on the initial navigation #189582

Description

@davidmigloz

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

  1. Create a GoRouter with an onEnter callback that returns Block.stop() for the initial location, and provide an onException handler.
  2. 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    c: crashStack traces logged to the consolef: routesNavigator, Router, and related APIs.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packagepackageflutter/packages repository. See also p: labels.team-frameworkOwned by Framework team

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions