Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Effect callback from asyncAction will run on rootZone, which causes UncaughtException. #873

Open
Elvis5566 opened this issue Sep 30, 2022 · 3 comments
Assignees
Labels
bug Something isn't working

Comments

@Elvis5566
Copy link

Elvis5566 commented Sep 30, 2022

In flutter, we use a custom zone to catch all exceptions from async operation.
The effect callback should run on the same zone as calling reaction, however,
if we change observable via asyncAction, the effect callback will run on RootZone.
This seems a serious issue, because we cannot get exception report from production build.
Am I misunderstanding? or is there a way to make effect run on the guarded zone even if we use AsyncAction?

Update:
This issue causes by using two AsyncActions, say we have two asyncActions A and B, A triggers reaction, then in the reaction handler, we call B.
If there is an exception in B, neither guardedZone nor reaction onError can catch the exception.

sample_uncaughtException

@Elvis5566 Elvis5566 changed the title effect callback from asyncAction will run on rootZone, which causes UncaughtException. Effect callback from asyncAction will run on rootZone, which causes UncaughtException. Sep 30, 2022
Elvis5566 pushed a commit to Elvis5566/mobx.dart that referenced this issue Sep 30, 2022
Elvis5566 pushed a commit to Elvis5566/mobx.dart that referenced this issue Sep 30, 2022
@amondnet
Copy link
Collaborator

amondnet commented Oct 3, 2022

@Elvis5566
#853 (comment)

By default, MobX will catch and re-throw exceptions happening in your code to make sure that a reaction in one exception does not prevent the scheduled execution of other, possibly unrelated, reactions. This means exceptions are not propagated back to the original causing code and therefore you won't be able to catch them using try/catch.

By disabling error boundaries, exceptions can escape derivations. This might ease debugging, but might leave MobX and by extension your application in an unrecoverable broken state.

@Elvis5566 Elvis5566 reopened this Oct 7, 2022
@Elvis5566
Copy link
Author

Elvis5566 commented Oct 11, 2022

I realized that this issue has nothing to do with disableErrorBoundaries.
Say we have two asyncActions A and B, A triggers reaction, then in the reaction handler, we call B.
If there is an exception in B, neither guardedZone nor reaction onError can catch that exception.
Here is sample code.

sample_uncaughtException

@Elvis5566 Elvis5566 reopened this Oct 11, 2022
@amondnet
Copy link
Collaborator

@Elvis5566 Yes there is a problem when using asyncAction with reaction. I'm making an asyncReaction but it takes some time. There is currently no clear workaround.

  1. Do not use asyncAction in reaction. Use sync action or do not throw exception.

    reaction((_) => store.value, (_) {
          store.async2().catchError((error) {
            print('catchError :$error');
          });
        });
  2. Use result.

reaction((_) => store.value, (_) {
      store.async2().then((result) {
        if (result.isError ) {
          print(result.asError!.error);
        }
      });
    });
import 'dart:async';

import 'package:async/async.dart';
import 'package:mobx/mobx.dart';

// Include generated file
part 'counter.g.dart';

// This is the class used by rest of your codebase
class Counter = _Counter with _$Counter;

// The store-class
abstract class _Counter with Store {
  @observable
  int value = 0;

  @action
  Future<void> incrementAsync() async {
    await Future.delayed(Duration(milliseconds: 200));
    value++;
  }

  @action
  Future<Result<void>> async2() async {
    try {
      await Future.delayed(Duration(milliseconds: 200));
      throw Exception("test2");
    } catch (e) {
      // don't throw exceptions.
      print('error');
      return Result.error(e);
    }
  }
}

@amondnet amondnet self-assigned this Oct 12, 2022
@amondnet amondnet added the bug Something isn't working label Oct 12, 2022
Elvis5566 pushed a commit to Elvis5566/mobx.dart that referenced this issue Apr 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants