question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Retrofit 2.0.1 + okhttp 3.2.0: GET not working when connected to WiFi network (SocketTimeoutException)

See original GitHub issue

I’ve found what appears to be a bug when performing a GET request to a private API. What is peculiar about this issue is the fact that even though it sometimes occurs when the Android device is connected to the mobile data network (around 10% of the time), on WiFi it just will never work, under any circumstance.

I’ve tested the same GET request using Postman, the private API’s swagger interface, and on iOS (AFNetworking), but when trying to get the Android app to perform the exact same request using Retrofit and okhttp, it fails to complete the request.

The response is JSON-formatted, and I’m using a GsonBuilder to deserialize it and turn it into a list of Java entity objects, as one would normally do. The response body is turned into a JsonReader through the GsonBuilder, which is then looped through using the hasNext() method, which in turn throws an IOException in the form of a SocketTimeoutException when waiting for the server to continue submitting data - this is done library-side. It looks like the serializer is able to serialize the first pack of data correctly, but the second one never arrives and that causes a peek() method to throw the exception.

I’m currently intercepting the request and response which show the following info (I’ve removed the address since it’s a private API I’m sending it to):

ApiManager: Sending request ********************* on null

ApiManager: Received response for ********************* Server: nginx/1.6.2 Vary: Accept, Cookie Cache-Control: max-age=600 Content-Type: application/json Date: Thu, 28 Apr 2016 20:36:37 GMT Expires: Thu, 28 Apr 2016 20:42:57 GMT Transfer-Encoding: chunked Connection: Keep-Alive Allow: GET, HEAD, OPTIONS X-Frame-Options: SAMEORIGIN Last-Modified: Thu, 28 Apr 2016 20:32:57 GMT OkHttp-Sent-Millis: 1461875797821 OkHttp-Received-Millis: 1461875798035

Here’s what I believe to be the relevant part of the code:


    @GET(ApiConstants.ENDPOINT)
    Call<List<Entity>> getEntityList();


    ...

    public ApiManager( .... ) {

        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(
                    new Interceptor() {
                        @Override
                        public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
                            Request request = chain.request();

                            request = request.newBuilder()
                                    .addHeader(ApiConstants.AUTH_HEADER, ApiConstants.AUTH_VALUE)
                                    .build();
                            okhttp3.Response response = chain.proceed(request);

                            return response;
                        }
                    })
                .build();

        Gson gson = new GsonBuilder()
                .registerTypeAdapter(Entity.class, new EntityDeserializer())
                .create();

        mRetrofitClient = new Retrofit.Builder()
                .baseUrl(ApiConstants.BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

        mApiService = mRetrofitClient.create(ApiInterface.class);

   ......

 mApiManager.getService().getEntityList().enqueue(new Callback<List<Entity>>() {
            @Override
            public void onResponse(Call<List<Entity>> call, Response<List<Entity>> response) {
               //Success
            }

            @Override
            public void onFailure(Call<List<Entity>> call, Throwable t) {
               //Always falls here on WiFi, gets SocketTimeoutException.
            }
        });

Finally, here’s the exception:

> 04-28 14:50:50.432 3463-3463/com.package.dev W/System.err: java.net.SocketTimeoutException: timeout
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at okio.Okio$3.newTimeoutException(Okio.java:212)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at okio.AsyncTimeout.exit(AsyncTimeout.java:288)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at okio.AsyncTimeout$2.read(AsyncTimeout.java:242)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at okio.RealBufferedSource.read(RealBufferedSource.java:45)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at okhttp3.internal.http.Http1xStream$ChunkedSource.read(Http1xStream.java:426)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at okio.RealBufferedSource.read(RealBufferedSource.java:45)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at okio.ForwardingSource.read(ForwardingSource.java:35)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at retrofit2.OkHttpCall$ExceptionCatchingRequestBody$1.read(OkHttpCall.java:279)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at okio.RealBufferedSource$1.read(RealBufferedSource.java:367)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at java.io.InputStreamReader.read(InputStreamReader.java:233)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at com.google.gson.stream.JsonReader.fillBuffer(JsonReader.java:1293)
> 04-28 14:50:50.435 3463-3463/com.package.dev W/System.err:     at com.google.gson.stream.JsonReader.peekKeyword(JsonReader.java:626)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:583)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.stream.JsonReader.peek(JsonReader.java:429)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.bind.TypeAdapters$29.read(TypeAdapters.java:720)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.bind.TypeAdapters$29.read(TypeAdapters.java:743)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.bind.TypeAdapters$29.read(TypeAdapters.java:718)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.Streams.parse(Streams.java:48)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:54)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:116)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:116)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:106)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at okhttp3.RealCall$AsyncCall.execute(RealCall.java:133)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err:     at java.lang.Thread.run(Thread.java:818)
> 04-28 14:50:50.436 3463-3463/com.package.dev W/System.err: Caused by: java.net.SocketTimeoutException
> 04-28 14:50:50.439 3463-3463/com.package.dev W/System.err:     at java.net.PlainSocketImpl.read(PlainSocketImpl.java:484)
> 04-28 14:50:50.439 3463-3463/com.package.dev W/System.err:     at java.net.PlainSocketImpl.-wrap0(PlainSocketImpl.java)
> 04-28 14:50:50.439 3463-3463/com.package.dev W/System.err:     at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
> 04-28 14:50:50.439 3463-3463/com.package.dev W/System.err:     at okio.Okio$2.read(Okio.java:140)
> 04-28 14:50:50.439 3463-3463/com.package.dev W/System.err:     at okio.AsyncTimeout$2.read(AsyncTimeout.java:238)
> 04-28 14:50:50.439 3463-3463/com.package.dev W/System.err:    ... 31 more

Best case scenario, I’ve done something obviously wrong and you guys will point me in the right direction. If not, I’d appreciate any workarounds or potential ways to debug this issue and eventually resolve it. I’ve been doing some reading, and it seems to me like this is not a necessarily new thing, but from what I can see similar reports belong to previous versions of the library, and proposed fixes seem arbitrary and not well substantiated.

One of these, for example, involved disabling the tcp_timestamp parameter in the sysctl file on the server. However, I have no access to the file or the server and I’m not going to approach them without an explanation on why that would solve the issue. I’m mentioning it here because hopefully someone will be knowledgeable enough to tell me if that’s a good solution/thing to try and why, so I can try that, but I’m crossing my fingers that won’t be necessary.

Thanks for the attention. I can happily provide any more info if needed.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:25 (5 by maintainers)

github_iconTop GitHub Comments

11reactions
cheflingAnshcommented, Mar 7, 2018

@Fireblend Hi, Even i facing the similar issue . One of the api’s doesn’t fetch me the result and throw socketTimeout exception. Could you solve the issue? Any help would be appriciated

3reactions
Pradhi11commented, May 10, 2018

Hi, Even i facing the same issue any help would be appriciated

Read more comments on GitHub >

github_iconTop Results From Across the Web

SocketTimeoutException in Retrofit - android - Stack Overflow
Your application will try to load the content even if the server is responding after a long time - It's a workaround, not...
Read more >
Consuming APIs with Retrofit | CodePath Android Cliffnotes
The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp. See this guide to understand ......
Read more >
MCA_Open_Source_Notices_An...
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, ...
Read more >
Meet Retrofit2 - allegro.tech blog
I also defined socket's connect and read timeouts and asked OkHttp to automatically retry whenever one of three network problems occurs ...
Read more >
Retrofit 2 - Handle Connection Timeout Exception
Generally in the android app, we do not care which type of timeout error was occurred because it all boils down to slow...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found