41

I am getting a IllegalStateException error in the Rx Library and don't know exactly where the root of the issue is, whether it is with RxJava or something I may be doing incorrectly.

The fatal crash occurs when certificate pinning (occurs on all server requests) but seems to point to a session timeout or logout and back in. Repro steps (occures about 25% of the time) are as follows: login, open list item - scroll all the way end - logout - logback in - open app - close app -> Crash!

Anyone have any ideas on how to prevent this? I found a similar issue here Observer.onError firing off inconsistently

java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
   at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:62)
   at android.os.Handler.handleCallback(Handler.java:615)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4867)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
   at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: rx.exceptions.OnErrorFailedException: Error occurred when trying to propagate error to Observer.onError
   at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:201)
   at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:111)
   at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:159)
   at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
   at android.os.Handler.handleCallback(Handler.java:615)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4867)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
   at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: rx.exceptions.CompositeException: 2 exceptions occurred. 
   at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:201)
   at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:111)
   at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:159)
   at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
   at android.os.Handler.handleCallback(Handler.java:615)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4867)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
   at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: rx.exceptions.CompositeException$CompositeExceptionCausalChain: Chain of Causes for CompositeException In Order Received =>
   at com.crashlytics.android.SessionDataWriter.getEventAppExecutionExceptionSize(SessionDataWriter.java:597)
   at com.crashlytics.android.SessionDataWriter.getEventAppExecutionExceptionSize(SessionDataWriter.java:600)
   at com.crashlytics.android.SessionDataWriter.getEventAppExecutionExceptionSize(SessionDataWriter.java:600)
   at com.crashlytics.android.SessionDataWriter.getEventAppExecutionSize(SessionDataWriter.java:533)
   at com.crashlytics.android.SessionDataWriter.getEventAppSize(SessionDataWriter.java:492)
   at com.crashlytics.android.CrashlyticsUncaughtExceptionHandler.writeSessionEvent(CrashlyticsUncaughtExceptionHandler.java:956)
   at com.crashlytics.android.CrashlyticsUncaughtExceptionHandler.access$200(CrashlyticsUncaughtExceptionHandler.java:56)
   at com.crashlytics.android.CrashlyticsUncaughtExceptionHandler$7.call(CrashlyticsUncaughtExceptionHandler.java:274)
   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
   at java.util.concurrent.FutureTask.run(FutureTask.java:137)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
   at io.fabric.sdk.android.services.common.ExecutorUtils$1$1.onRun(ExecutorUtils.java:58)
   at io.fabric.sdk.android.services.common.BackgroundPriorityRunnable.run(BackgroundPriorityRunnable.java:13)
   at java.lang.Thread.run(Thread.java:856)
Community
  • 1
  • 1
Scott B
  • 1,478
  • 2
  • 16
  • 26
  • Hi Scott. Any possibility of knowing Android version, RxJava version, RxAndroid version, please? Are you properly disposing all your subscriptions? – Ivan Morgillo Aug 11 '15 at 20:32
  • io.reactivex:rxandroid:0.24.0 io.reactivex:rxjava:1.0.12 `Android version 5.1` And yes I am unsubscribing all of my subscriptions and then settineg them to null – Scott B Aug 11 '15 at 22:24
  • Can you try RxAndroid 1.0.1https://github.com/ReactiveX/RxAndroid/releases/tag/v1.0.1 please? – Ivan Morgillo Aug 12 '15 at 07:34
  • Thanks @IvanMorgillo I will do that and see if this is still happening. Thank you – Scott B Aug 13 '15 at 21:28

4 Answers4

52

What's happening is that your onError implementation in a Subscriber is throwing an unchecked exception which is against the Observable contract and this aborts the observable processing throwing an OnErrorFailedException in the observeOn scheduler.

Dave Moten
  • 11,957
  • 2
  • 40
  • 47
  • It's worth pointing on that if you try to debug this by logging inside your `onError` implementation, you may not see it in logcat. You are best debugging with breakpoints. This is what kept me from initially seeing the problem. – tir38 May 09 '17 at 22:35
  • How can I track the exact error in `onError()` callback instead of receiving this generic stacktrace? – Roman Nazarevych Jun 12 '17 at 12:48
  • 1
    how to fix? You are receiving a Throwable in your implementation of onError and then causing another error in the processing of that error. I would fix your implementation so it does not do that. To help you debug you could log the thrown error by wrapping your onError implementation with try catch. – Dave Moten Aug 23 '17 at 06:29
14

You are probably passing an Activity context somewhere from your onError callback. This was happening to me when I tried to show an AlertDialog - passing to it a specific Activity context - and pressing back button before that dialog came up. My advice is to not pass Activity contexts this way.

IgorGanapolsky
  • 26,189
  • 23
  • 116
  • 147
2

This is how I solved the issue:

public abstract class MyNetworkSubscriber<T> extends Subscriber<T> {

@Override
public void onCompleted() {}

@Override
public void onError(Throwable e) {
    if (e instanceof HttpException) {
        ResponseBody responseBody = ((HttpException) e).response().errorBody();
        try {
            if (responseBody != null) {
                MyError error = new Gson().fromJson(responseBody.string(), MyError.class);
                onErrorCode(error);
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    } else {
        e.printStackTrace();
    }
}

public void onErrorCode(MyError error){};
}

For some reason, OkHttp was forcing me to catch onError so I did. If I did not do this, OkHttp/Retrofit will crash and the app will shut down.

By providing this solution,

  1. you can choose to override your own onErrorCode and get a more detailed object back as error which comes from your API but you don't have to.
  2. OnError is overridden, no more crazy crashes.
  3. And last but not least it is still generic because of <T>!

You can also force onComplete & onError to be overriden to make the methods abstract.

Karl-John Chow
  • 775
  • 2
  • 8
  • 26
0

if you want update UI in onError,just try:

api.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber(){....})
rayjun
  • 33
  • 5