Catching Exceptions from Dart Isolates

Issue

I’m having trouble working out how I can catch exceptions from isolates. With the following code, I’ve tried everything I can think of to handle the error that is thrown from task, but it’s still marked as Unhandled exception.

void main() async {
  try {
    var rp = ReceivePort();

    rp.listen((message) {
      print(message);
    }, onError: (e) {
      print(e);
    });
    rp.handleError((e) {
      print(e);
    });
    var isolate = await Isolate.spawn(task, rp.sendPort);
    isolate.addErrorListener(rp.sendPort);
  } catch (e) {
    print(e);
  }
}

void task(SendPort sp) {
  sp.send('hello from isolate');
  throw Exception();
}

What am I missing here?

EDIT: From the below answer, my solution should look like this:

void main() async {
  var rp = ReceivePort();
  var errorRp = ReceivePort();
  errorRp.listen((e) {
    print('exception occured');
    print(e);
  });
  rp.listen(print);
  await Isolate.spawn(task, rp.sendPort, onError: errorRp.sendPort);
  await Future.delayed(Duration(seconds: 1));
  rp.close();
  errorRp.close();
}

void task(SendPort sp) {
  sp.send('hello from isolate');
  throw Exception();
}

Solution

I think you have missed an important segment of the documentation for Isolate.spawn:

You can also call the setErrorsFatal, addOnExitListener and addErrorListener methods on the returned isolate, but unless the isolate was started as paused, it may already have terminated before those methods can complete.

You issue is that your spawned Isolate has already executed throw Exception() before your isolate.addErrorListener(rp.sendPort); has been executed.

Instead, do something like this to spawn the Isolate as paused and then later resume it:

    var isolate = await Isolate.spawn(task, rp.sendPort, paused: true);
    isolate.addErrorListener(rp.sendPort);
    isolate.resume(isolate.pauseCapability!);

Alternative, you can just give the Isolate your error handler as part of spawning:

var isolate = await Isolate.spawn(task, rp.sendPort, onError: rp.sendPort);

Answered By – julemand101

Answer Checked By – Clifford M. (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.