- Issue: flutter/flutter#183012
- Live demo: https://davidmigloz.github.io/flutter_block_then_bug/
Block.then(() => router.go(...)) callbacks in go_router's onEnter handler silently lose their navigation when triggered by refreshListenable. The router.go() inside the callback runs synchronously during handleTopOnEnter processing, triggering a re-entrant _processRouteInformation whose result is dropped due to transaction token churn in Flutter's Router.
- Run the app:
flutter run -d chrome
- App starts authenticated on
/home(green indicator should show if already fixed). - Tap "Sign Out" to set
isAuthenticated = false. refreshListenablefires, theonEnterguard returnsBlock.then(() => router.go('/login')).
The app navigates to /login (green "FIXED" indicator).
The app stays on /home (red "BUG" indicator). The debug console shows [Block.then] Calling router.go(/login) confirming the callback fires, but the navigation is lost.
The callback at parser.dart:533 fires during the outer parse's Future chain via await Future<void>.sync(callback). When the callback calls router.go('/login'), it synchronously triggers a new _processRouteInformation via notifyListeners(). Flutter's Router mints a new transaction token, and the re-entrant parse's result is dropped due to token churn.
In parser.dart, change await Future<void>.sync(callback) to scheduleMicrotask(() async { await callback(); }). This defers the callback to the microtask queue, ensuring router.go() runs after the current parse has completed and Flutter's Router has committed the result.
- go_router: 17.1.0 (fork with
onEnterAPI) - Flutter: 3.41.2 (stable)
- Dart SDK: 3.11.0 (stable)