Skip to content

Assertion failed: "onGenerateRoute" shows assertion when I try to go the same route for the 2nd time. #44128

Closed

Description

@ClozedJP

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:

  1. 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

  1. changed the title [-]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.[/+] on Nov 5, 2019
  2. iapicca commented on Nov 5, 2019

    @iapicca

    Hi @ClozedJP
    thank you for reporting that,
    I noticed that it occurs also with the demo code

    doctor
    [√] Flutter (Channel dev, v1.10.14, on Microsoft Windows [Version 10.0.18362.10024], locale en-US)
        • Flutter version 1.10.14 at C:\src\flutter
        • Framework revision 1946fc4da0 (4 weeks ago), 2019-10-07 15:23:31 -0700
        • Engine revision 1d62160fdb
        • Dart version 2.6.0 (build 2.6.0-dev.5.0 d6c6d12ebf)
    
    
    [√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
        • Android SDK at C:\Users\iapic\AppData\Local\Android\sdk
        • Android NDK location not configured (optional; useful for native profiling support)
        • Platform android-28, build-tools 28.0.3
        • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
        • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
        • All Android licenses accepted.
    
    [√] Chrome - develop for the web
        • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
    
    [√] Android Studio (version 3.5)
        • Android Studio at C:\Program Files\Android\Android Studio
        • Flutter plugin version 40.0.2
        • Dart plugin version 191.8423
        • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
    
    [√] VS Code, 64-bit edition (version 1.39.2)
        • VS Code at C:\Program Files\Microsoft VS Code
        • Flutter extension version 3.6.0
    
    [√] Connected device (2 available)
        • Chrome          • chrome          • web-javascript • Google Chrome 77.0.3865.120
        • Headless Server • headless-server • web-javascript • Flutter Tools
    
    • No issues found!
    
  3. added
    f: routesNavigator, Router, and related APIs.
    c: crashStack traces logged to the console
    platform-webWeb applications specifically
    on Nov 5, 2019
  4. ClozedJP commented on Nov 7, 2019

    @ClozedJP
    Author

    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.

    class Alternateway extends StatelessWidget {
      static final int initialVal = 0;
      static final int finalVal = 9;
      final Map widgetMap = {};
      Alternateway() {    
        for (int i = initialVal; i < finalVal + 1; i++) {
          TextWithButton twb = TextWithButton(i);
          widgetMap[i.toString()] = twb;
        }
      }
    
      Route<dynamic> generateRouteBySwitchTest(RouteSettings settings) {
        print("settings.name:" + settings.name);
        Widget target = widgetMap[settings.name];
        if(target == null){
          target = widgetMap["0"];
        }    
        return MaterialPageRoute(builder: (context) => target);
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Reproduce',
          routes: {"/": (context) => widgetMap["0"], },
          onGenerateRoute: generateRouteBySwitchTest,
        );
      }
    }
    
    class TextWithButton extends StatelessWidget {
      final int current;
    
      TextWithButton(int current)
          : this.current = current;
      @override
      Widget build(BuildContext context) {
        List<Widget> lw = [];
        int pre = current - 1;
        int next = current + 1;
        lw.add(Text("Current:" + current.toString()));
        if (current > Alternateway.initialVal)
          lw.add(FlatButton(
            child: Text("go to:" + pre.toString()),
            onPressed: () {
              Navigator.popAndPushNamed(context, pre.toString());
            },
          ));
        if (current < Alternateway.finalVal)
          lw.add(FlatButton(
            child: Text("go to:" + next.toString()),
            onPressed: () {
              Navigator.popAndPushNamed(context, next.toString());
            },
          ));
        return Row(
          children: lw,
        );
      }
    }
  5. yjbanov commented on Nov 7, 2019

    @yjbanov
    Contributor

    /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.

  6. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    and removed
    platform-webWeb applications specifically
    on Nov 7, 2019
  7. ClozedJP commented on Nov 8, 2019

    @ClozedJP
    Author

    It would be nice if I am able to chose "Always dispose" vs "Always Keep."
    just like "maintainState" property in "MaterialPageRoute" class.

  8. ClozedJP commented on Nov 8, 2019

    @ClozedJP
    Author

    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

  9. goderbauer commented on Nov 11, 2019

    @goderbauer
    Member

    @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 call Navigator.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.

  10. ClozedJP commented on Nov 12, 2019

    @ClozedJP
    Author

    thx for reply @goderbauer I understand the 1st paragraph.

    1. Re-use of route objects is prohibited.
    2. Even if I want to use the route with same name, I should make the new route object
    3. My alternate is the way to go since it ”new MaterialPageRoute and populate it with a builder from a Map”

    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.

  11. goderbauer commented on Nov 12, 2019

    @goderbauer
    Member

    Yes, the assert on this line [1] should have an error message telling you that the pushed route has already been used.

    [1]

    assert(route._navigator == null);

  12. self-assigned this
    on Jul 2, 2020
  13. added this to the 1.21 - July 2020 milestone on Jul 2, 2020
  14. github-actions commented on Aug 19, 2021

    @github-actions

    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 -v and a minimal reproduction of the issue.

  15. locked as resolved and limited conversation to collaborators on Aug 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

a: error messageError messages from the Flutter frameworkc: crashStack traces logged to the consolef: routesNavigator, Router, and related APIs.frameworkflutter/packages/flutter repository. See also f: labels.waiting for PR to land (fixed)A fix is in flight

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions