Repository navigation
Assertion failed: "onGenerateRoute" shows assertion when I try to go the same route for the 2nd time. #44128
Description
Condition:
-
using Chrome-Develop for the web
-
using "flutter channel master" 2019-11-5 tokyo
("flutter version" shows tons of v 1.XX.XX . so I am not sure what to write here)
Step:
- With the code below, start the app by "flutter run -d chrome"
2.Click "to the Home" button.
3.Click "to the Root" button.
4.You see the Red Screen with the assertion message.
Comment:
-
as you can see from the code, I have tested using onGenerateRoute with the switch case. This works.
-
but what I want to achieve is to create routing table from setting file. which probably need Map
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final Map rootMap;
MyApp():
rootMap = {
"/": MaterialPageRoute(builder:(context) => Root()),
'/Home': MaterialPageRoute(builder:(context) => Home()),
};
Route<dynamic> generateRouteByMap(RouteSettings settings) {
if(rootMap[settings.name] != null){
return rootMap[settings.name];
}
else{
return MaterialPageRoute(builder:(context) => Root());
}
}
Route<dynamic> generateRouteBySwitch(RouteSettings settings) {
switch(settings.name){
case "/Home":
return MaterialPageRoute(builder:(context) => Home());
default:
return MaterialPageRoute(builder:(context) => Root());
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Reproduce',
// routes: {
// "/": (context) => Root(),
// "/Home": (context) => Home(),
// },
// onGenerateRoute: generateRouteBySwitch,
onGenerateRoute: generateRouteByMap,
);
}
}
class Root extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Text("Root"),
FlatButton(
child: Text("to the Home"),
onPressed: () {
Navigator.popAndPushNamed(context, "/Home");
},
),
],
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Text("home"),
FlatButton(
child: Text("to The Root"),
onPressed: () {
Navigator.popAndPushNamed(context, "/");
},
),
],
);
}
}and the Assertion message is following
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following assertion was thrown while handling a gesture:
Assertion failed: org-dartlang-app:///packages/flutter/src/widgets/navigator.dart:1788:12
route._navigator == null
is not true
package:flutter/src/gestures/binding.dart 156:7
[_handlePointerEvent]
package:flutter/src/gestures/binding.dart 102:7
[_flushPointerEventQueue]
package:flutter/src/gestures/binding.dart 86:32
[_handlePointerDataPacket]
package:build_web_compilers/src/dev_compiler/C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/pointer_binding.dart 89:15
[_onPointerData]
package:build_web_compilers/src/dev_compiler/C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/pointer_binding.dart 261:7
package:build_web_compilers/src/dev_compiler/C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/pointer_binding.dart 173:16
Handler: "onTap"
Recognizer:
TapGestureRecognizer#0a0fa
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: Assertion failed: org-dartlang-app:///packages/flutter/src/widgets/navigator.dart:2330:12
Activity
[-]Assertion failed: org-dartlang-app:///packages/flutter/src/widgets/navigator.dart:1788:12[/-][+]Assertion failed: "onGenerateRoute" shows assertion when I try to go the same route for the 2nd time.[/+]iapicca commentedon Nov 5, 2019
Hi @ClozedJP
thank you for reporting that,
I noticed that it occurs also with the demo code
doctor
ClozedJP commentedon Nov 7, 2019
I just came up with alternate of achieving what I want.
Just in case someone want to do the same stuff, I leave the code here.
update: somehow, sometimes work without 'routes: {"/": (context) => Loading(), }'sometimes not.
yjbanov commentedon Nov 7, 2019
/cc @goderbauer this is an example of a confusing behavior in the navigator when the route is push again after being popped out of and disposed. This is not a web-only issue, so removing the web label.
ClozedJP commentedon Nov 8, 2019
It would be nice if I am able to chose "Always dispose" vs "Always Keep."
just like "maintainState" property in "MaterialPageRoute" class.
ClozedJP commentedon Nov 8, 2019
More Info:
I meet the error while I was looking for the alternate to this case. I am not able to make it simple.
This error must be related or similar to this case. I hope this will help.
Error massage is below.
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following assertion was thrown while handling a gesture:
Assertion failed: org-dartlang-app:///packages/flutter/src/widgets/navigator.dart:2113:12
!_debugLocked
is not true
Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
When the exception was thrown, this was the stack:
package:build_web_compilers/src/dev_compiler/C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 194:49 throw
package:build_web_compilers/src/dev_compiler/C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 24:3 assertFailed
package:flutter/src/widgets/navigator.dart 2113:13 pop
package:flutter/src/widgets/navigator.dart 1736:5 popAndPushNamedpackage:flutter/src/widgets/navigator.dart 1027:32 popAndPushNamedpackage:adventure/adventure/visual/ActionBars.dart 56:33
package:flutter/src/material/ink_well.dart 706:14 [_handleTap]
package:flutter/src/material/ink_well.dart 789:36
package:flutter/src/gestures/recognizer.dart 182:24 invokeCallback
package:flutter/src/gestures/tap.dart 486:47 handleTapUp
package:flutter/src/gestures/tap.dart 264:5 [_checkUp]
package:flutter/src/gestures/tap.dart 236:7 acceptGesture
package:flutter/src/gestures/arena.dart 156:12 sweep
package:flutter/src/gestures/binding.dart 222:20 handleEvent
package:flutter/src/gestures/binding.dart 198:14 dispatchEvent
package:flutter/src/gestures/binding.dart 156:7
[_handlePointerEvent]
package:flutter/src/gestures/binding.dart 102:7
[_flushPointerEventQueue]
package:flutter/src/gestures/binding.dart 86:32
[_handlePointerDataPacket]
package:build_web_compilers/src/dev_compiler/C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/pointer_binding.dart 89:15
[_onPointerData]
package:build_web_compilers/src/dev_compiler/C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/pointer_binding.dart 261:7
package:build_web_compilers/src/dev_compiler/C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/pointer_binding.dart 173:16
Handler: "onTap"
Recognizer:
TapGestureRecognizer#ac7dd
goderbauer commentedon Nov 11, 2019
@iapicca The example you link to works as expected for me.
In general, it is not a good idea to re-use route objects (they have a lifecycle of their own and if you re-push the same Route object you will run into problems). Whenever you push a route you want to provide a new Route object. So, in your generateRouteByMap you probably always want to create a new MaterialPageRoute and populate it with a builder from a Map or something like that.
In this particular case the problem is that you currently cannot pop the first route off the history stack. So, your first call to
Navigator.popAndPushNamed(context, "/Home");will not remove the route/from the history because it is the first route. When you then callNavigator.popAndPushNamed(context, "/");you are essentially pushing a Route object that's already on the history stack and that's when the exception throws because one-and-the-same Route object cannot be on the stack twice.ClozedJP commentedon Nov 12, 2019
thx for reply @goderbauer I understand the 1st paragraph.
But, I am not sure about 2nd paragraph.
You say “...So, your first call to Navigator.popAndPushNamed(context, "/Home"); will not remove the route...”
yet, if i pop the “/Home” then the “/” is not exist, there was white screen. I think the "/" is poped.
However, I think this is not the focus of the topic here.
Anyway, I understand this is not a bug, but The error message is not user friendly.
I think, this is very common mistake we would make for 1st time.
It would be nice if the error message was saying about “not a good idea to re-use route objects (they ... problems)”
If you want me to close this case let me know.
goderbauer commentedon Nov 12, 2019
Yes, the assert on this line [1] should have an error message telling you that the pushed route has already been used.
[1]
flutter/packages/flutter/lib/src/widgets/navigator.dart
Line 1788 in 99055c7
github-actions commentedon Aug 19, 2021
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.