Skip to content

[go_router]: "There is nothing to pop" when popped fast #145573

@eli1stark

Description

@eli1stark

Steps to reproduce

Steps:

  1. go_router: v12.1.3
  2. Launch sample
  3. Press 'Push And Pop" button

Explanation:

This issue occurs when pushing and popping pages rapidly enough. Adding a delay of 100-200ms seems to fix the issue, but this is not an optimal solution in my opinion. It's more of a hack that unnecessarily delays app interactions in the hope of avoiding the bug.

Here's an example use case for this issue and why you might need to pop a newly pushed page very quickly. A good use case would be when a Future completes fast enough, like so:

router.pushPageA();

final status = await future();

if (status.isSuccess) {
  router.pushSomeOtherPage();
} else {
  router.pop(); // close PageA
}

In this example, you push PageA, await for a Future to complete, and based on the status, either push another page or pop PageA. If the Future completes quickly, the pop operation happens immediately after the push, causing the issue.

Expected results

PageB should be popped without errors.

Actual results

The error 'There is nothing to pop' occurs when attempting to pop a newly pushed PageB. A pop occurs before GoRouter is able to acknowledge the new route (PageB).

Code sample

Code sample
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

final router = GoRouter(
  routes: [
    GoRoute(
      name: 'A',
      path: '/',
      builder: (_, __) => const PageA(),
    ),
    GoRoute(
      name: 'B',
      path: '/B',
      builder: (_, __) => const PageB(),
    ),
  ],
);

void main() => runApp(const App());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: router,
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: TextButton(
              onPressed: () {
                context.pushNamed('B');
                context.pop();
              },
              child: const Text('Push And Pop'),
            ),
          ),
        ],
      ),
    );
  }
}

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

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

Logs

Logs
Restarted application in 835ms.

════════ Exception caught by gesture ═══════════════════════════════════════════
The following GoError was thrown while handling a gesture:
There is nothing to pop

When the exception was thrown, this was the stack:
#0      GoRouterDelegate.pop (package:go_router/src/delegate.dart:94:5)
delegate.dart:94
#1      GoRouter.pop (package:go_router/src/router.dart:490:20)
router.dart:490
#2      GoRouterHelper.pop (package:go_router/src/misc/extensions.dart:71:65)
extensions.dart:71
#3      PageA.build.<anonymous closure> (package:offsuit/main_development.dart:46:25)
main_development.dart:46
#4      _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1183:21)
ink_well.dart:1183
#5      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:275:24)
recognizer.dart:275
#6      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:652:11)
tap.dart:652
#7      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:309:5)
tap.dart:309
#8      BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:242:7)
tap.dart:242
#9      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:630:9)
recognizer.dart:630
#10     PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
pointer_router.dart:98
#11     PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
pointer_router.dart:143
#12     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13)
compact_hash.dart:633
#13     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
pointer_router.dart:141
#14     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
pointer_router.dart:127
#15     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:488:19)
binding.dart:488
#16     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:468:22)
binding.dart:468
#17     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:439:11)
binding.dart:439
#18     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:413:7)
binding.dart:413
#19     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:376:5)
binding.dart:376
#20     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:323:7)
binding.dart:323
#21     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:292:9)
binding.dart:292
#22     _invoke1 (dart:ui/hooks.dart:328:13)
hooks.dart:328
#23     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:410:7)
platform_dispatcher.dart:410
#24     _dispatchPointerDataPacket (dart:ui/hooks.dart:262:31)
hooks.dart:262

Handler: "onTap"
Recognizer: TapGestureRecognizer#832a5
    debugOwner: GestureDetector
    state: possible
    won arena
    finalPosition: Offset(226.0, 447.0)
    finalLocalPosition: Offset(78.6, 19.0)
    button: 1
    sent tap down
════════════════════════════════════════════════════════════════════════════════

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.16.7, on macOS 14.2.1 23C71 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.3)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.3)
[✓] VS Code (version 1.86.2)
[✓] Connected device (3 available)
[✓] Network resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listfound in release: 3.19Found to occur in 3.19found in release: 3.21Found to occur in 3.21has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packagepackageflutter/packages repository. See also p: labels.team-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions