Fatal Exception thrown on Scheduler.Worker thread with Retrofit 2 and Rx

This is the code I use to make Http call. I can't reproduce the error, but Bugsnag tells me that some users are getting this error : java.lang.IllegalStateException StrictMode.java

public class ApiManager {
    public interface Callback<T> {
        void onError(Throwable e);

        void onSuccess(T result);
    }

    private ApiService _apiService;

    public ApiManager() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(ew OkHttpClient())
                .build();
        _apiService = retrofit.create(ApiService.class);
    }

    private <T> void execute(Observable<T> observable, final Callback<T> callback) {
        observable.subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<T>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                        callback.onError(e);
                    }

                    @Override
                    public void onNext(T result) {
                        callback.onSuccess(result);
                    }
                });
    }

    public void createUser(Callback<Void> callback) {
        execute(_apiService.createUser(new User()), callback);
    }

    // Retrofit Service
    public interface ApiService {
        @POST("users")
        Observable<Void> createUser(@Body User user);
    }
}

Here is the full trace :

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:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:153)
        at android.app.ActivityThread.main(ActivityThread.java:5340)
        at java.lang.reflect.Method.invokeNative(Method.java:-2)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
        at dalvik.system.NativeStart.main(NativeStart.java:-2)
Caused by: rx.exceptions.UnsubscribeFailedException
        at rx.observers.SafeSubscriber.onCompleted(SafeSubscriber.java:98)
        at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.pollQueue(OperatorObserveOn.java:195)
        at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:162)
        at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
        at android.os.Handler.handleCallback(Handler.java:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:153)
        at android.app.ActivityThread.main(ActivityThread.java:5340)
        at java.lang.reflect.Method.invokeNative(Method.java:-2)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
        at dalvik.system.NativeStart.main(NativeStart.java:-2)
Caused by: android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1128)
        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:906)
        at com.squareup.okhttp.Connection.closeIfOwnedBy(Connection.java:148)
        at com.squareup.okhttp.OkHttpClient$1.closeIfOwnedBy(OkHttpClient.java:75)
        at com.squareup.okhttp.internal.http.HttpConnection.closeIfOwnedBy(HttpConnection.java:137)
        at com.squareup.okhttp.internal.http.HttpTransport.disconnect(HttpTransport.java:135)
        at com.squareup.okhttp.internal.http.HttpEngine.disconnect(HttpEngine.java:573)
        at com.squareup.okhttp.Call.cancel(Call.java:122)
        at retrofit.OkHttpCall.cancel(OkHttpCall.java:162)
        at retrofit.RxJavaCallAdapterFactory$CallOnSubscribe$1.call(RxJavaCallAdapterFactory.java:102)
        at rx.subscriptions.BooleanSubscription.unsubscribe(BooleanSubscription.java:71)
        at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:124)
        at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:113)
        at rx.Subscriber.unsubscribe(Subscriber.java:98)
        at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:124)
        at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:113)
        at rx.Subscriber.unsubscribe(Subscriber.java:98)
        at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:124)
        at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:113)
        at rx.Subscriber.unsubscribe(Subscriber.java:98)
        at rx.observers.SafeSubscriber.onCompleted(SafeSubscriber.java:95)
        at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.pollQueue(OperatorObserveOn.java:195)
        at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:162)
        at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
        at android.os.Handler.handleCallback(Handler.java:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:153)
        at android.app.ActivityThread.main(ActivityThread.java:5340)
        at java.lang.reflect.Method.invokeNative(Method.java:-2)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
        at dalvik.system.NativeStart.main(NativeStart.java:-2)

I also tried to subscribe on Sheduler.io() and Scheduler.newThread(), but I get the same error.

Upvotes: 6

Views: 16923

Answers (4)

Loyea
Loyea

Reputation: 3569

My experience & suggests:

Check your onError(Throwable e) and onCompleted() method implement of Subscriber, is any possible may cause any exception. For example, NullPointerException etc.

Rxjava can not catch the exception which throw from this two method. And you will get java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread. Which you even can't locate the exception source from the stack trace.

Upvotes: 1

GaminTsai
GaminTsai

Reputation: 1

Something wrong occur in Observable.create() if you not catch will case this question.

Observable.create((Subscriber<? super Object subscriber) -> { // something wrong occur in here ,you can surround these codes by try catch });

Upvotes: 0

It looks like upgrading to com.squareup.retrofit2:retrofit:2.0.2 using okhttp3solved the problem.

Upvotes: 1

Fred
Fred

Reputation: 17095

Note this isn't a permanent fix, but it helped me and might help you. It's too long to put in a comment.

While I was using the specific version of retrofit you've mentioned I noticed there was a bug (already being addressed) with the okhttp library and the rx integration with retrofit.

I don't know the state of the fix, but I have a quick fix which was adding to the rx stream unsubscribeOn(Schedulers.io()), like so:

observable.subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.io())
            .subscribe(new Subscriber<T>() {
                @Override
                public void onCompleted() {
                }

                @Override
                public void onError(Throwable e) {
                    callback.onError(e);
                }

                @Override
                public void onNext(T result) {
                    callback.onSuccess(result);
                }
            });

Upvotes: 5

Related Questions