Catch error using catchError in a future and throw another type

Your solution should work (simply throw another exception), but a more expressive way is probably to use Future.error:

Future<void> someApi() {
  return Future(() {
    throw FirstError();
  }).catchError((error, stackTrace) {
    print("inner: $error");
    // although `throw SecondError()` has the same effect.
    return Future.error(SecondError());
  });
}

and then use

  someApi()
    .then((val) { print("success"); })
    .catchError((error, stackTrace) {
      // error is SecondError
      print("outer: $error");
    });

You can play around with it at: https://dartpad.dartlang.org/8fef76c5ba1c76a23042025097ed3e0a


We have in the flutter framework the description for the catch function:

  • Handles errors emitted by this [Future].
    • This is the asynchronous equivalent of a "catch" block. ... Future catchError(Function onError, {bool test(Object error)});

When chaining futures I would advise against of using:

throw error;

and instead use:

return Future.error(SecondError());

This is because if you chain a future and expect to catch the error using the catchError future you will have the following problem.

Future<void> _refresh() {
  return throw Exception("Exception");
}

void main() {
    _refresh() // .then((_) => print("bla"))
    .catchError(() => print("not able to be reached"));
}

And you will get an error Uncaught exception: Exception: Exception.

This is similar when using RX (in general) and instead of throwing you send down the chain a Sigle.error (or any other observable with error).


TLDR:

When working with Futures and chaining them (including catchError) use Future.error(Exception("Exception")) to handle errors.

If you are using throw make sure or surround with try catch or Future(() -> throw ... )