Skip to content

Crash on Navigator.push when current route has nested Navigator containing pages with Heros #28042

@spkersten

Description

@spkersten

Minimal example:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(home: Root());
}

class Root extends StatelessWidget {
  @override
  Widget build(BuildContext context) => Navigator(
        onGenerateRoute: (settings) => MaterialPageRoute(builder: (context) => Page1()),
      );
}

class Page1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: GestureDetector(
          onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => Page2())),
          child: Hero(
            tag: "superman",
            child: Container(width: 40, height: 40, color: Colors.red),
          ),
        ),
      ),
    );
  }
}

class Page2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Hero(
            tag: "superman",
            child: GestureDetector(
                onTap: () => Navigator.of(context, rootNavigator: true)
                    .push(MaterialPageRoute(fullscreenDialog: true, builder: (context) => Modal())),
                child: Container(width: 60, height: 60, color: Colors.red))),
      ),
    );
  }
}

class Modal extends StatelessWidget {
  @override
  Widget build(BuildContext context) => Scaffold(backgroundColor: Colors.purple);
}

Tapping the red square twice results in:

flutter: ══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following assertion was thrown during a scheduler callback:
flutter: There are multiple heroes that share the same tag within a subtree.
flutter: Within each subtree for which heroes are to be animated (typically a PageRoute subtree), each Hero
flutter: must have a unique non-null tag.
flutter: In this case, multiple heroes had the following tag: superman
flutter: Here is the subtree for one of the offending heroes:
flutter: # Hero(tag: superman, state: _HeroState#0b567)
flutter: # └KeyedSubtree-[GlobalKey#5c93c]
flutter: #  └Container(bg: BoxDecoration(color: MaterialColor(primary value: Color(0xfff44336))), constraints: BoxConstraints(w=40.0, h=40.0))
flutter: #   └ConstrainedBox(BoxConstraints(w=40.0, h=40.0), renderObject: RenderConstrainedBox#48feb relayoutBoundary=up4)
flutter: #    └DecoratedBox(bg: BoxDecoration(color: MaterialColor(primary value: Color(0xfff44336))), dependencies: [_LocalizationsScope-[GlobalKey#91878], Directionality, MediaQuery], renderObject: RenderDecoratedBox#7672f)
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      Hero._allHeroesFor.visitor.<anonymous closure> (package:flutter/src/widgets/heroes.dart:210:15)
flutter: #1      Hero._allHeroesFor.visitor (package:flutter/src/widgets/heroes.dart:220:12)

In our case Root is a widget having several tabs, each with their own Navigator, while the root Navigator is used to (among other things) show modals route on (which should cover the tabbar).

This seems to be the cause of #25362 and #25218, but the issue is more generic.

[✓] Flutter (Channel master, v1.2.2-pre.21, on Mac OS X 10.14.3 18D109, locale en-NL)
    • Flutter version 1.2.2-pre.21 at /Users/spkersten/Development/flutter
    • Framework revision 035e0765cc (3 hours ago), 2019-02-16 01:48:28 -0500
    • Engine revision f37b09a11b
    • Dart version 2.1.2 (build 2.1.2-dev.0.0 c92d5ca288)

Metadata

Metadata

Assignees

No one assigned

    Labels

    c: crashStack traces logged to the consolecustomer: solarisf: routesNavigator, Router, and related APIs.frameworkflutter/packages/flutter repository. See also f: labels.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions