Retrofit: Asynchronous Error Handling on Network in retrofit v2 beta 2

Created on 5 Nov 2015  路  11Comments  路  Source: square/retrofit

Please help to fix it out,
how to handle network error in asynchronous?

@Override
public void onFailure(Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
when request timeout t.getMessage() is null.

i want catch exception on onFailure(Throwable t) to show like :

  1. no internet connection
  2. request timeout
  3. internal error!
  4. Invalid credentials

please help to write detail because i'm a beginner android.

sorry for my bad english.

Thank you

Most helpful comment

When the Throwable passed to the failure callback is an IOException, this means that it was a network problem (socket timeout, unknown host, etc.). Any other exception means something broke either in serializing/deserializing the data or it's a configuration problem.

You can t instanceof IOException to determine network problem and react appropriately.

A 401 (or any non-2xx response code) will actually go to the response callback, because it was a successful response even though it may not have been a successful operation on the server. You can check this in onResponse by calling response.isSuccess().

All 11 comments

Hello @phirumtan!

You can process errors "no internet connection"(IOException), "request timeout"(SocketTimeoutException) inside onFailure(Throwable).

new Callback<ResponseEntity>() {
            @Override
            public void onResponse(Response<ResponseEntity> response, Retrofit retrofit) {
                latch.countDown();
            }

            @Override
            public void onFailure(Throwable t) {
                try {
                    ErrorBundle errorBundle = ErrorBundle.adapt(t);
                    assertThat(errorBundle.getAppMessage(), is("Authorization exception"));
                } finally {
                    latch.countDown();
                }
            }
        }

In regard of 401 Unauthorized errors you can either catch code inside interceptor of OkHttp client and rethrow unchecked exception that will be delegated to onFailure method.

        OkHttpClient client = new OkHttpClient();
        client.interceptors().add(new Interceptor() {
            @Override
            public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                com.squareup.okhttp.Response response = chain.proceed(request);

                boolean unAuthorized = (response.code() == 401);
                if (unAuthorized) {
                    throw new AuthorizeException();
                }
                return response;
            }
        });

Or you can handle 401 code inside onResponse(Response<?>, Retrofit) callback.

For details take a look in THIS REPO

When the Throwable passed to the failure callback is an IOException, this means that it was a network problem (socket timeout, unknown host, etc.). Any other exception means something broke either in serializing/deserializing the data or it's a configuration problem.

You can t instanceof IOException to determine network problem and react appropriately.

A 401 (or any non-2xx response code) will actually go to the response callback, because it was a successful response even though it may not have been a successful operation on the server. You can check this in onResponse by calling response.isSuccess().

now i cleared everything.
Thank you tomkoptel and JakeWharton.

What kind of exceptions can we expect in onFailure method. Only timeouts and connect errors?

@JakeWharton in the IOException, how do I differentiate between timeout vs unknown host or any other kind of problem? I would like to crashlytics log this properly if possible, and also show appropriate UI messages

@bhargavms you'll get a better answer, sooner by asking this question on stack overflow.

throw new AuthorizeException() is not getting caught in onFailure.
If I write throw new IOException() in onIntercept(), onFailure() of retrofit 2 gets called but not in other exceptions which dismiss the meaning of our own exception.

How should I throw a custom exception in ResponseInterceptor so that it gets caught by onFailure()?

@JakeWharton

When the Throwable passed to the failure callback is an IOException, this means that it was a network problem (socket timeout, unknown host, etc.). Any other exception means something broke either in serializing/deserializing the data or it's a configuration problem

I got java.io.EOFException because of a deserializing problem which is basically an IOException.

java.io.EOFException: End of input at line 1 column 1 
    at com.google.gson.stream.JsonReader.nextNonWhitespace(JsonReader.java:1408)
    at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:553)
    at com.google.gson.stream.JsonReader.peek(JsonReader.java:429)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:201)
    at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
    at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
    at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:116)
    at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
    at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:106)
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:133)
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
    at java.lang.Thread.run(Thread.java:818)

@tomkoptel your link is not found in this comment.

@richakhanna Have you created your custom Exception?

@pratikbutani for those of you who are looking for @tomkoptel's ErrorBundle class from his comment, you can find a copy of it here:
https://github.com/divyamary/PopularMovies_Final/blob/50389d04ef3f8fcf9f9520c669157a1f721c67de/app/src/main/java/in/divyamary/moviereel/api/ErrorBundle.java

Was this page helpful?
0 / 5 - 0 ratings