-
Notifications
You must be signed in to change notification settings - Fork 7.6k
How to throw an exception from within an Observer #969
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
Comments
According to Rx contract, |
I understand that onError is called only once, I'm not trying to forward the exception to something else. What I want to do is be able to throw a RuntimeException to make the app terminate. |
RxJava will catch |
I get why catching all errors from within the flow of RxJava (ie observables, functions etc..) to keep the monadic properties but once you reach the Observer the flow is consumed and this the point in the app where you can act on the events. The idea here is to fail fast in order to identify easily developer errors during the development phase. I was under the assumption after reading this closed issue #650 that RxJava should not be swallowing exceptions from within an Observer. |
#650 is out of date. The |
I didn't realise that some operator might be using Observers internally, makes more sense now. |
This is an odd use case ... and it skips over the Not ideal at all. I think we may need to make See here for the |
Re-throw when onError throws an Exception. This fixes ReactiveX#969
Re-throw when onError throws an Exception. This fixes ReactiveX#969
Sorry for reviving an old discussion. We also run into the same issue, and the change that went in does not really help us. Rx contract or not, I think I agree with @Dorvaryn that certain errors should simply terminate the app, since they can signal developer error rather than anticipated runtime errors. A good example are precondition checks and assertions. Guava for instance throws IllegalArgumentException when a precondition failed. This will throw during an The way this is dealt with right now:
While I do see your points, I think there is definitely a case to be made for failing early, outside the Rx contract (since you want to terminate the app, why would breaking the Rx contract matter anyway?) It would go a long way to make Rx based apps easier to debug, since more often than not, errors you expect to fail the app simply disappear in the safe guards applied by SafeSubscriber. |
Actually, a much simpler way to solve this would be to change Was there any particular reason why only 4 kinds of errors are rethrown from |
Generally errors should be emitted to onError otherwise systems can end up hanging and/or leak resources because they never receive a terminal event (onComplete/onError) and therefore never releases user requests, unsubscribed for cleanup, etc. Only fatal errors are thrown, and the OnErrorNotImplementedException after the terminal event ensures everything receives an unsubscribe. Ben Christensen
|
Sure, but why is something like |
The definition of fatal exceptions can definitely be changed. Here is what we will want to change: https://github.com/Netflix/RxJava/blob/master/rxjava-core/src/main/java/rx/exceptions/Exceptions.java#L82 |
Would you be okay with replacing these 4 checks with |
Perhaps. Should AssertionError be considered fatal though? When we say fatal here it really does mean the app may die it need to be killed as user requests may be hung if this happens. |
In our case, I feel an assertion failure should kill the app, but I see It also looks like a potential source of bugs due to duplication: maybe |
The If The contract for error handling in Rx is:
A try/catch/finally isn't reliable when multiple threads are involved, this is why it's so important to route errors to Can we step back and clearly define the use case trying to be solved? I want to understand if it's the actual Rx contract above that is in question, or just a bug in an operator or choice of "fatal" exceptions that needs to be fixed. |
I see, that makes sense. The use case we're trying to address is discovering developer failure The result is that our app continues to run in a broken or undefined state, |
What does your onError handler do with the exception when it receives it? |
It checks it for its type and then decides if it should rethrow or report |
Since your final On the other hand, if a developer doesn't implement Considering these two possibilities, what about this current state isn't working for you? |
I believe part of the problem is
That is, it catches all errors and loops them through the global onError hook, which is not allowed to throw. So even if |
That said, just from my perspective, what we could do is to let the developer decide what fatal means when an exception is caught. This could be as simple as providing a predicate Plus, we need to make sure that this logic is executed in all internal classes the catch Throwable. Otherwise we'll end up swallowing errors that shouldn't be swallowed. |
Definitely.
If the user provided
Agreed. If scheduled work fails it has no choice but to throw an exception wherever it is, such as here: Work being scheduled should never throw, but instead propagate to |
Makes sense. I'm not sure I understand what you're suggesting though. All our observables are scheduled, so whatever the subscriber does won't matter, as it will end up in this catch clause. Does that mean there is no way for us to achieve what I outlined? |
I'm saying that the operators that do scheduling should do the error handling. For example, I see that If the operator doesn't do it, a user has no hope of managing errors. |
Hi ,My use case is to propagate the error from Observable to subscriber,but the same error is not visible to onError() method of subscriber ,instead it always shows @Override
protected Observable<String> construct() {
System.out.println("I am in construct of "+name+"::thread name: "+Thread.currentThread().getName());
return Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> observer) {
try {
if (!observer.isUnsubscribed()) {
String response = HTTPClientHelper.searchSR("https://stg-step.am.health.ge.com/service/v2/service-event11/search/SHOWROOM24", "gJc1Ts8PWBrCmi5PcTtZJTk6JmyS", "212469169");
// a real example would do work like a network call here
observer.onNext(response + "!");
observer.onCompleted();
}
} catch (Exception e) {
System.out.println("Exception+++++++++++++++"+e.getMessage());
observer.onError(new RuntimeException("graceful onError"));
}
}
} ); |
Despite you are using 1.x |
ok sure thanks |
Sorry for reviving an old discussion again, but can someone help me?
Is this still viable for RxJava 2? |
Hi,
I am trying to make the app fail fast when something is going wrong from the Observer.
I was surprised to see that the Exception was swallowed by RxJava.
Here is a sample I tried :
Do I need do do anything specific to fail from within an Observer ?
The text was updated successfully, but these errors were encountered: