Skip to content

ModalBarrier has imperfect error message #125385

@fzyzcjy

Description

@fzyzcjy

Is there an existing issue for this?

Steps to reproduce

Hi thanks for the wonderful Flutter! It seems that, when ModalBarrier.onDismiss callback throws error, Flutter says "Exception was thrown while routing a pointer event" while for normal callbacks it should say "Exception was thrown while handling a gesture". For a new learner of Flutter, they may gets confused what is a "pointer event" while "a gesture" looks more consistent and friendly to new learners.

Indeed, I raise the PR because I hacked the invokeCallback, and run into trouble at ModalBarrier because it does not call invokeCallback at all. Then I checked the source code and think this is a bit of inconsistency, so I make the PR ;)

Run the test code shown below (at bottom, folded).

Expected results

After #125386:

══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following _Exception was thrown while handling a gesture:
Exception: deliberate

When the exception was thrown, this was the stack:
#0      main.<anonymous closure>.<anonymous closure> (file:///Users/tom/Main/yplusplus/frontend/common_flutter/test/hi.dart:11:28)
#1      ModalBarrier.build.handleDismiss (package:flutter/src/widgets/modal_barrier.dart:120:21)
#2      _AnyTapGestureRecognizer.handleTapUp.<anonymous closure> (package:flutter/src/widgets/modal_barrier.dart:259:49)
#3      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:255:24)
#4      _AnyTapGestureRecognizer.handleTapUp (package:flutter/src/widgets/modal_barrier.dart:259:5)
#5      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:306:5)
#6      BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:239:7)
#7      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:617:9)
#8      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
#9      PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
#10     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:625:13)
#11     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
#12     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
#13     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:462:19)
#14     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:442:22)
#15     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:336:11)
#16     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:395:7)
#17     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:357:5)
#18     TestWidgetsFlutterBinding.handlePointerEventForSource.<anonymous closure> (package:flutter_test/src/binding.dart:573:42)
#19     TestWidgetsFlutterBinding.withPointerEventSource (package:flutter_test/src/binding.dart:583:11)
#20     TestWidgetsFlutterBinding.handlePointerEventForSource (package:flutter_test/src/binding.dart:573:5)
#21     WidgetTester.sendEventToBinding.<anonymous closure> (package:flutter_test/src/widget_tester.dart:819:15)
#24     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#25     WidgetTester.sendEventToBinding (package:flutter_test/src/widget_tester.dart:818:27)
#26     TestGesture.up.<anonymous closure> (package:flutter_test/src/test_pointer.dart:554:26)
#29     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#30     TestGesture.up (package:flutter_test/src/test_pointer.dart:547:27)
#31     WidgetController.tapAt.<anonymous closure> (package:flutter_test/src/controller.dart:511:21)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from dart:async and package:stack_trace)

Handler: "onTapUp"
Recognizer:
  _AnyTapGestureRecognizer#58655
════════════════════════════════════════════════════════════════════════════════════════════════════
-------- the extra --------
extra: {}
-------- Above is an extra dumpErrorToConsole configured from test_config.dart --------
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════

Actual results

══╡ EXCEPTION CAUGHT BY GESTURE LIBRARY ╞═══════════════════════════════════════════════════════════
The following _Exception was thrown while routing a pointer event:
Exception: deliberate

When the exception was thrown, this was the stack:
#0      main.<anonymous closure>.<anonymous closure> (file:///Users/tom/Main/yplusplus/frontend/common_flutter/test/hi.dart:11:28)
#1      ModalBarrier.build.handleDismiss (package:flutter/src/widgets/modal_barrier.dart:120:21)
#2      _AnyTapGestureRecognizer.handleTapUp (package:flutter/src/widgets/modal_barrier.dart:259:17)
#3      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:306:5)
#4      BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:239:7)
#5      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:617:9)
#6      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
#7      PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
#8      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:625:13)
#9      PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
#10     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
#11     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:462:19)
#12     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:442:22)
#13     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:336:11)
#14     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:395:7)
#15     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:357:5)
#16     TestWidgetsFlutterBinding.handlePointerEventForSource.<anonymous closure> (package:flutter_test/src/binding.dart:573:42)
#17     TestWidgetsFlutterBinding.withPointerEventSource (package:flutter_test/src/binding.dart:583:11)
#18     TestWidgetsFlutterBinding.handlePointerEventForSource (package:flutter_test/src/binding.dart:573:5)
#19     WidgetTester.sendEventToBinding.<anonymous closure> (package:flutter_test/src/widget_tester.dart:819:15)
#22     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#23     WidgetTester.sendEventToBinding (package:flutter_test/src/widget_tester.dart:818:27)
#24     TestGesture.up.<anonymous closure> (package:flutter_test/src/test_pointer.dart:554:26)
#27     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#28     TestGesture.up (package:flutter_test/src/test_pointer.dart:547:27)
#29     WidgetController.tapAt.<anonymous closure> (package:flutter_test/src/controller.dart:511:21)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from dart:async and package:stack_trace)

router: Instance of 'PointerRouter'
route: Closure: (PointerEvent) => void from Function 'handleEvent':.
event: _TransformedPointerUpEvent#75a45(position: Offset(400.0, 300.0))
════════════════════════════════════════════════════════════════════════════════════════════════════

Code sample

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

void main() {
  testWidgets('ModalBarrier', (tester) async {
    final barrierKey = UniqueKey();
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: ModalBarrier(
          key: barrierKey,
          onDismiss: () => throw Exception('deliberate'),
        ),
      ),
    ));
    await tester.tap(find.byKey(barrierKey));
    await tester.pump();
  });
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[Paste your output here]

Comparison

For example, say we are using GestureDetector.onTap - which should be analogy to ModalBarrier.onDismiss:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('ModalBarrier', (tester) async {
    final key = UniqueKey();
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: GestureDetector(
          key: key,
          onTap: () => throw Exception('deliberate'),
        ),
      ),
    ));
    await tester.tap(find.byKey(key));
    await tester.pump();
  });
}

gives

══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following _Exception was thrown while handling a gesture:
Exception: deliberate

When the exception was thrown, this was the stack:
...

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: error messageError messages from the Flutter frameworkfound in release: 3.10Found to occur in 3.10found in release: 3.7Found to occur in 3.7frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work on

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions