Repository navigation
Predictive back can close app when navigation stack is not empty #145290
Copy link
Copy link
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listf: routesNavigator, Router, and related APIs.Navigator, Router, and related APIs.found in release: 3.19Found to occur in 3.19Found to occur in 3.19found in release: 3.21Found to occur in 3.21Found to occur in 3.21has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packageThe go_router packageplatform-androidAndroid applications specificallyAndroid applications specificallyteam-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem teamworkaround availableThere is a workaround available to overcome the issueThere is a workaround available to overcome the issue
Description
Steps to reproduce
- add
android:enableOnBackInvokedCallback="true"to main/AndroidManifest.xml - run the code below
- go to /home/second by tapping IconButton
- open modalBottomSheet by tapping IconButton
- swipe to go back -> modalBottomSheet closes
- swipe to go back -> app exits
Expected results
after step 6 we should be at /home page
(and if there is no android:enableOnBackInvokedCallback="true" - bug doesn't appear)
Actual results
after step 6 we go to desktop
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final dispatcher = BackDispatcher();
return MaterialApp.router(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
// routerConfig: router,
routerDelegate: router.routerDelegate,
routeInformationProvider: router.routeInformationProvider,
routeInformationParser: router.routeInformationParser,
backButtonDispatcher: dispatcher,
);
}
}
class BackDispatcher extends RootBackButtonDispatcher {
@override
Future<bool> didPopRoute() async {
if (modalStack.isNotEmpty) {
debugPrint('popping modal');
Navigator.of(navKey.currentContext!).pop();
return true;
}
return super.didPopRoute();
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('home page'),
),
body: Center(
child: IconButton(
onPressed: () => context.go('/home/second'),
icon: const Icon(Icons.link),
),
),
);
}
}
class SecondPage extends StatelessWidget {
const SecondPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('second page'),
),
body: Center(
child: IconButton(
onPressed: () {
showModalBottomSheet(
context: context,
useRootNavigator: true,
builder: (context) {
return Container(
width: 100,
height: 100,
color: Colors.red,
);
},
);
},
icon: const Icon(Icons.slideshow),
),
),
);
}
}
class Layout extends StatelessWidget {
const Layout(
this.shell, {
super.key,
});
final StatefulNavigationShell shell;
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(child: shell),
Container(
height: 10,
color: Colors.blueGrey,
),
],
);
}
}
final modalStack = <Route>[];
class MyObserver extends RouteObserver {
@override
void didPush(Route route, Route? previousRoute) {
if (previousRoute == null) return;
debugPrint('!!! didPush ${route.runtimeType}');
modalStack.add(route);
super.didPush(route, previousRoute);
}
@override
void didPop(Route route, Route? previousRoute) {
debugPrint('!!! didPop ${route.runtimeType}');
modalStack.removeLast();
super.didPop(route, previousRoute);
}
}
final navKey = GlobalKey<NavigatorState>();
GoRouter router = GoRouter(
debugLogDiagnostics: true,
observers: [MyObserver()],
initialLocation: '/home',
navigatorKey: navKey,
routes: [
GoRoute(
path: '/',
redirect: (_, state) {
return state.fullPath == '/' ? '/home' : null;
},
routes: [
StatefulShellRoute.indexedStack(
builder: (context, state, shell) => Layout(shell),
branches: [
StatefulShellBranch(
routes: [
GoRoute(
path: 'home',
builder: (context, _) => const MyHomePage(),
routes: [
GoRoute(
path: 'second',
builder: (context, _) => const SecondPage(),
),
],
),
],
),
],
),
],
),
],
);
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.19.3, on macOS 14.3.1 23D60 darwin-arm64, locale en-RU)
• Flutter version 3.19.3 on channel stable at /opt/homebrew/Caskroom/flutter/3.10.4/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision ba39319843 (10 days ago), 2024-03-07 15:22:21 -0600
• Engine revision 2e4ba9c6fb
• Dart version 3.3.1
• DevTools version 2.31.1
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
• Android SDK at /Users/geara0/Library/Android/sdk
✗ cmdline-tools component is missing
Run `path/to/sdkmanager --install "cmdline-tools;latest"`
See https://developer.android.com/studio/command-line for more details.
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 15C500b
• CocoaPods version 1.15.2
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2023.1)
• Android Studio at /Users/geara0/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 17.0.7+0-17.0.7b1000.6-10550314)
[✓] IntelliJ IDEA Ultimate Edition (version 2023.1.1)
• IntelliJ at /Users/geara0/Applications/IntelliJ IDEA Ultimate.app
• 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
[✓] VS Code (version 1.87.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.84.0
[✓] Connected device (4 available)
• M2101K6G (mobile) • 79a46fc6 • android-arm64 • Android 13 (API 33)
• sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 14 (API 34) (emulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 14.3.1 23D60 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 122.0.6261.129
! Error: Browsing on the local area network for iPhone HOME. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources
• All expected network resources are available.
! Doctor found issues in 1 category.Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listf: routesNavigator, Router, and related APIs.Navigator, Router, and related APIs.found in release: 3.19Found to occur in 3.19Found to occur in 3.19found in release: 3.21Found to occur in 3.21Found to occur in 3.21has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packageThe go_router packageplatform-androidAndroid applications specificallyAndroid applications specificallyteam-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem teamworkaround availableThere is a workaround available to overcome the issueThere is a workaround available to overcome the issue
Activity
[-]Predictive back can close app when navigationstack is not empty[/-][+]Predictive back can close app when navigation stack is not empty[/+]darshankawar commentedon Mar 18, 2024
@Geara0
Can you take a look at https://docs.flutter.dev/release/breaking-changes/android-predictive-back and see if it helps in your case or not ?
Geara0 commentedon Mar 18, 2024
@darshankawar
No, migration guide can't help me in this case, because key functions in this example is
showModalBottomSheet(context, useRootNavigator: true)Navigator.of(navKey.currentContext!).pop();and
didPopRoute from RootBackButtonDispatcherwhich are functions that came from the default flutter package
then, GoRouter should handle pop in NestedRoute, but app closes even before GoRouter registers any event
Why I think it's not GoRouter issue?
https://github.com/flutter/packages/blob/a757073ac4eaf05b7516d3d0488e5c98b221043f/packages/go_router/lib/src/router.dart#L186
I put debugPoints everywhere across flutter and go_router source files and saw that flutter calls function (can't find it rn, maybe will come back to that later) that does following
Why even use GoRouter then?
Idk how to create nested routes with flutter only, but I'm sure that issue will occur even if I rebuild app with flutter default navigation (if possible)
darshankawar commentedon Mar 19, 2024
Thanks for the update. Check below issues and see if they resemble your case or not:
#140869
#139398
Geara0 commentedon Mar 19, 2024
@darshankawar
#140869 is not related bc
android:enableOnBackInvokedCallbackdoesn't affect this issue(same result when true/false)
#139398 is not realted bc my issue isn't go_router issue
(And go router works fine in my case.)
As I said earlier
My issue is about
android:enableOnBackInvokedCallbackvalue affecting how nested routing worksif false - all works fine
if true - nested navigation doesn't receive pop callback, instead app closes
and this close app behaviour is handled by flutter itself
darshankawar commentedon Mar 20, 2024
Thanks for the update. I was able to replicate the reported behavior using details provided.
stable, master flutter doctor -v
35 remaining items
flutter-triage-bot commentedon Oct 9, 2025
This issue was assigned to @justinmc but has had no status updates in a long time. To remove any ambiguity about whether the issue is being worked on, the assignee was removed.
Henry-Hiles commentedon Oct 5, 2026
Can confirm this still happens for me on Flutter 3.47.4, where a drawer is in the stack but the entire app closes on predictive back.