Skip to content

[go_router] Duplicate GlobalKey detected in widget tree when a navigatorKey is used on a nested ShellRoute #112181

Open

Description

@tonyrbf96

Tested on

  • go_router: 5.0.1

Steps to Reproduce

  1. Execute flutter run on the code sample
  2. Tap on BottomNavigationBar's buttons. (More faster than page transition)
Code sample
final GlobalKey<NavigatorState> _navigatorKey =
    GlobalKey<NavigatorState>(debugLabel: 'shell');

final router = GoRouter(
  initialLocation: '/a',
  routes: [
    ShellRoute(
      builder: (context, state, child) => HomePage(child: child),
      routes: [
        ShellRoute(
          navigatorKey: _navigatorKey,
          builder: (context, state, child) => child,
          routes: [
            GoRoute(
              path: '/a',
              builder: (context, state) => const PageA(),
            )
          ],
        ),
        GoRoute(
          path: '/b',
          builder: (context, state) => const PageB(),
        )
      ],
    )
  ],
);

void main() {
  runApp(
    MaterialApp.router(
      routeInformationParser: router.routeInformationParser,
      routeInformationProvider: router.routeInformationProvider,
      routerDelegate: router.routerDelegate,
    ),
  );
}

class HomePage extends StatelessWidget {
  const HomePage({super.key, required this.child});
  final Widget child;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: GoRouter.of(context).location.startsWith('/a') ? 0 : 1,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.navigate_before),
            label: 'A',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.navigate_next),
            label: 'B',
          )
        ],
        onTap: (value) {
          if (value == 0) {
            context.go('/a');
          } else {
            context.go('/b');
          }
        },
      ),
      body: child,
    );
  }
}

class PageA extends StatelessWidget {
  const PageA({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: Colors.blue,
    );
  }
}

class PageB extends StatelessWidget {
  const PageB({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: Colors.red,
    );
  }
}
Logs


════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
Multiple widgets used the same GlobalKey.

The key [LabeledGlobalKey<NavigatorState>#2b85e shell] was used by multiple widgets. The parents of those widgets were:
- Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#d87b0)
- Semantics(container: false, properties: SemanticsProperties, tooltip: null, renderObject: RenderSemanticsAnnotations#9f6a5)
A GlobalKey can only be specified on one widget at a time in the widget tree.
When the exception was thrown, this was the stack
#0      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure>.<anonymous closure>
package:flutter/…/widgets/framework.dart:2883
#1      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#2      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure>
package:flutter/…/widgets/framework.dart:2827
#3      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#4      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>
package:flutter/…/widgets/framework.dart:2822
#5      BuildOwner._debugVerifyGlobalKeyReservation
package:flutter/…/widgets/framework.dart:2891
#6      BuildOwner.finalizeTree.<anonymous closure>
package:flutter/…/widgets/framework.dart:2950
#7      BuildOwner.finalizeTree
package:flutter/…/widgets/framework.dart:3032
#8      WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:885
#9      RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:378
#10     SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1175
#11     SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1104
#12     SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:1015
#13     _invoke (dart:ui/hooks.dart:148:13)
#14     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#15     _drawFrame (dart:ui/hooks.dart:115:31)
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by widgets library ═══════════════════════════════════
Multiple widgets used the same GlobalKey.
════════════════════════════════════════════════════════════════════════════════

...

Analyzing app...                                                        
No issues found! (ran in 21.8s)
[✓] Flutter (Channel stable, 3.3.0, on macOS 12.5 21G72 darwin-x64, locale en-US)
    • Flutter version 3.3.0 on channel stable at /Users/tony/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision ffccd96b62 (3 weeks ago), 2022-08-29 17:28:57 -0700
    • Engine revision 5e9e0e0aa8
    • Dart version 2.18.0
    • DevTools version 2.15.0

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at /Users/tony/Library/Android/sdk
    • Platform android-31, build-tools 30.0.1
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 13F100
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1)
    • Android Studio at /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 1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.71.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.46.0

[✓] Connected device (3 available)
    • Tony Xr (mobile) • 00008020-000C11A23C02003A • ios            • iOS 15.4.1 19E258
    • macOS (desktop)  • macos                     • darwin-x64     • macOS 12.5 21G72 darwin-x64
    • Chrome (web)     • chrome                    • web-javascript • Google Chrome 97.0.4692.71

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

Activity

  1. added
    P2Important issues not at the top of the work list
    on Sep 22, 2022
  2. moved this to Todo in GoRouteron Sep 22, 2022
  3. mvarendorff2 commented on Jan 22, 2024

    @mvarendorff2

    We are hitting this as well in a GoRouter setup when re-rendering the router using riverpod (because dependencies change); it's rather frustrating and borderline impossible to debug :/

  4. toineheuvelmans commented on Mar 12, 2024

    @toineheuvelmans

    I've been hitting this same issue for the past days. I use a ShellRoute with a pageBuilder that, depending on the route, uses a CustomTransitionPage with no transition or one with a FadeTransition. When I comment out the use of the FadeTransition, everything works fine. This makes me believe that the issue maybe is caused due to the FadeTransition showing two routes simultaneously, cross-fading between them. Does that sound plausible? This would then be the same for any transition that does not do a hard switch between routes, I guess.

  5. yknevenky commented on Mar 15, 2024

    @yknevenky

    We are hitting this as well in a GoRouter setup when re-rendering the router using riverpod (because dependencies change); it's rather frustrating and borderline impossible to debug :/

    Hey, I have the same issue too. I too use a similar setup that's based on Riverpod provider and GRouter. Any solutions that you found out?. Thanks in advance.

  6. Trung15010802 commented on Mar 19, 2024

    @Trung15010802

    I have the same error

  7. tusaamf commented on Mar 19, 2024

    @tusaamf

    I have the same error

    Can you try create a static variable routeConfig like this.

    `
    class AppRouter {
    static GoRouter _routerConfig() {
    ...
    }
    }

    static final _routerConfig = AppRouter().routerConfig;

    @OverRide
    Widget build(BuildContext context) {
    return MaterialApp.router(
    // router
    routerConfig: _routerConfig,
    );
    }
    `

  8. yknevenky commented on Mar 19, 2024

    @yknevenky

    We are hitting this as well in a GoRouter setup when re-rendering the router using riverpod (because dependencies change); it's rather frustrating and borderline impossible to debug :/

    Hey I was able to escape the error, by including the global key declarations inside the routerProvider definition itself. So that each time a change occurs, the router body would rerun and different keys would be supplied. I am not sure whether am I right or wrong, but I was able to escape this issue.

  9. AxelBlaz3 commented on Apr 22, 2024

    @AxelBlaz3

    @yknevenky I ran into the same issue while using Riverpod with GoRouter. I believe moving the GlobalKey declarations insider the provider is the right fix!

  10. tolo commented on Sep 12, 2024

    @tolo

    This is likely related to, or a duplicate of, issue #148768. And possibly not a go_router issue, but instead an issue in Flutter (Navigator).

  11. jaybe78 commented on May 23, 2025

    @jaybe78

    I use flutter bloc and get it.
    Any idea how to solve that issue when not using riverpod ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listp: go_routerThe go_router packagepackageflutter/packages repository. See also p: labels.team-ecosystemOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem team

    Type

    No type

    Projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions