Home > database >  Why does runZonedGuarded prevent following code from executing?
Why does runZonedGuarded prevent following code from executing?

Time:10-05

Observe the following code.

void main() async {
  await runZonedGuarded(
    () async {
      print("a");
      throw "error";
    },
    (e, s) {
      print("b");
    },
  );
  print("c");
}

It only prints...

a
b

Instead of ...

a
b
c

If I remove the throw it prints

a
c

Can someone explain what exactly is going on here? Why does c not print in the first case?

Thanks!

CodePudding user response:

Dart has the notion of "error zones". When you introduce an error handler in a zone, any error future belonging to that zone will refuse to propagate its error to a future belonging to a different error zone.

The runZonedGuarded function installs an error handler to handle asynchronous errors, but that also means that the future you return, a Future<void>, belongs to that zone. You don't throw an error inside the runZonedGuarded, instead you return a future containing an error. The onError handler isn't triggered on the return.

When you then try to await the future, after having left the function, the error zone gets in the way. Instead of re-throwing the error at the await, it instead makes the error an uncaught error in the error zone (which is why it prints b), and then the future doesn't complete at all at the await. That's highly confusing.

See also: https://github.com/dart-lang/sdk/issues/39825

As a recommendation: Don't return futures from runZonedGuarded. That's ... not very usable, because the reason to use zones at all is to do asynchronous computations.

  • Related