5

Let's say in a Flutter app we want to catch any uncaught exceptions/errors at the top level, so we do this as per the docs:

main() {
  
  // All uncaught errors thrown from synchronous code blocks will end up here:
  FlutterError.onError = (FlutterErrorDetails details) {
    MyLogger.instance.logUncaughtErrorSync(details);
  };

  // All uncaught errors thrown from async code blocks will end up here:
  PlatformDispatcher.instance.onError = (Object error, StackTrace stack) {
    MyLogger.instance.logUncaughtErrorASync(error, stack);
    return true;
  };
  
  runApp(const MyApp());

While the docs seems to imply that the distinction between the two is whether the error originated in Dart (and specifically "Flutter") code vs platform (Android/IOS) code, through my testing, the only difference I can tell between the two is whether the Object (error) was thrown from async vs sync Dart code.

For example, if in Dart code, (not platform code), we simply put:

_function() async {
    throw('error');
}

and we call that function, it will bubble up through the "platform dispatcher" and is considered a "platform error," but seemingly only because it happened on a background thread?

The appears to actually be no mechanism allowing Exceptions thrown from Java or Swift code to trigger either of these onError functions.

There must be more to it than this though, so whats the point of having two separate mechanisms (with different inputs -- FlutterErrorDetails vs Object+StackTrace)... and what's the real difference?

Nerdy Bunz
  • 6,040
  • 10
  • 41
  • 100

1 Answers1

2

In fact, the answer is provided in the documentation page you referenced.

FlutterError.onError is meant for Flutter framework errors - errors that happen at the framework level (errors encountered during the build, layout, and paint phases). In simple words, if you have an error that happens because of your written Dart code or the one in the Flutter framework, it goes to FlutterError.onError.

On the other hand, PlatformDispatcher.instance.onError is meant for platform-level errors. As you may know, Flutter supports multiple platforms and those execute the code in their native layer. For instance, you use plugins or you implement your own Flutter plugin code using Platform channels:

OutlinedButton(
  child: const Text('Click me!'),
  onPressed: () async {
    const channel = MethodChannel('crashy-custom-channel')
    await channel.invokeMethod('blah')
  },
)

In such case, this is not a Flutter-level error anymore, thus it will be forwarded to PlatformDispatcher.instance.onError.

mkobuolys
  • 4,499
  • 1
  • 11
  • 27
  • 1
    Yes that was my initial understanding also, because of the naming they use and the examples they give, however after testing it it seems it has nothing whatsoever to do with the nature of the error and only whether not the error happed in sync dart code vs async dart code. For example in that button , you could have onPressed: () async {throw “poo”;} and it would still be a “platform error” – Nerdy Bunz Feb 04 '23 at 00:53