75

With OkHttp library, application is facing following SocketTimeoutException issue. If request size is less, then it is working fine(Less than 1MB). I am getting this exception within 10 seconds, even my socket timeout(readTimeout) value is much higher. It is consistently failing for a request(Size is 1.8MB). When I executed a request with HttpUrlConnection it is working fine. What could be a possible reason of failure?

   03-29 12:16:38.997 32066-4018/com.mobile W/System.err: java.net.SocketTimeoutException: timeout
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.Okio$3.newTimeoutException(Okio.java:207)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.AsyncTimeout.exit(AsyncTimeout.java:261)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.AsyncTimeout$1.write(AsyncTimeout.java:158)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:176)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.RealBufferedSink.write(RealBufferedSink.java:46)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.internal.http.Http1xStream$FixedLengthSink.write(Http1xStream.java:286)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:176)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.RealBufferedSink.write(RealBufferedSink.java:96)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.RequestBody$2.writeTo(RequestBody.java:96)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:704)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.internal.http.HttpEngine.readResponse(HttpEngine.java:563)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.RealCall.getResponse(RealCall.java:241)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at okhttp3.RealCall.execute(RealCall.java:57)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at com.mobizio.api.BaseApi.sendOkHttpRequest(BaseApi.java:81)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at com.mobizio.api.BaseApi.doInBackground(BaseApi.java:45)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at com.mobizio.api.BaseApi.doInBackground(BaseApi.java:30)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:292)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at java.lang.Thread.run(Thread.java:818)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err: Caused by: java.net.SocketException: socket is closed
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:759)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at okio.Okio$1.write(Okio.java:80)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at okio.AsyncTimeout$1.write(AsyncTimeout.java:155)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:  ... 20 more
2
  • Give your client a larger read time out value. Seems that time out is happening when the stream is read from the socket. Commented Apr 6, 2016 at 16:50
  • 1
    @NikolaDespotoski I already set Socket timeout to 15 minutes still I am facing this issue Commented Apr 7, 2016 at 4:58

10 Answers 10

73

For OkHttp 3 the default value for OkHttp is 10 seconds. You can increase the timeout to 30 seconds.

OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(30, TimeUnit.SECONDS); // connect timeout
client.setReadTimeout(30, TimeUnit.SECONDS);    // socket timeout
Sign up to request clarification or add additional context in comments.

6 Comments

I already set the connection timeout value to 30 seconds and socket timeout value to 15 minutes. Still I am facing the same issue and app is getting above exception within 10 seconds
@DBragion As per documentation provided by Square github.com/square/okhttp/wiki/Recipes. It is suggested that don't use this post string method if request size is more that 1MiB. You can fallback to HttpUrlConnection method or you need to implement post streaming at described in the document.
@Vivek -- did you ever find a solution? I'm experiencing something similar.
No implemente post streaming or use httpurlconnection
I have set to 5 min Still Im getting this issue
|
62

I solved that problem increasing writeTimeout().

Try:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(5, TimeUnit.MINUTES) // connect timeout
.writeTimeout(5, TimeUnit.MINUTES) // write timeout
.readTimeout(5, TimeUnit.MINUTES); // read timeout

okHttpClient = builder.build();

2 Comments

Setting also writeTimeout solved the problem, thanks :)
If we want to upload file, we have to change the default writeTimeout as mentioned above.
23

this resolved my problem:

OkHttpClient innerClient = new OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.MINUTES) // connect timeout
            .writeTimeout(5, TimeUnit.MINUTES) // write timeout
            .readTimeout(5, TimeUnit.MINUTES) // read timeout
            .build();

4 Comments

How is this any different than what others have commented?
There are no more setters like the first two (setConnectTimeout & setReadTimeout), and I think mine is more organized :) Also, none is marked as resolved ;)
Saved my day. I was about to mess around on the internet
I think its the prettiest solution so far
10

You need to understand that only adding this won't solve your problem:

OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)

If you are using Kotlin + Retrofit + Coroutines then just use try and catch for network operations like,

viewModelScope.launch(Dispatchers.IO) {
        try {
            val userListResponseModel = apiEndPointsInterface.usersList()
            returnusersList(userListResponseModel)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

Where, Exception is type of kotlin and not of java.lang

This will handle every exception like,

  1. HttpException
  2. SocketTimeoutException
  3. FATAL EXCEPTION: DefaultDispatcher etc

Here is my usersList() function

@GET(AppConstants.APIEndPoints.HOME_CONTENT)
suspend fun usersList(): UserListResponseModel

Comments

6

Use this for Kotlin

 val client1 = OkHttpClient.Builder()
                .connectTimeout(2, TimeUnit.MINUTES)
                .writeTimeout(2, TimeUnit.MINUTES) // write timeout
                .readTimeout(2, TimeUnit.MINUTES) // read timeout
                .addInterceptor(
                    BasicAuthInterceptor(
                        AmvaccAppConstants.AUTHENTICATE_USER_NAME, AmvaccAppConstants.AUTHENTICATE_USER_PASSWORD
                    )
                )
                .addInterceptor(interceptor)
                .build()

Comments

2

Incrementing the timeout is like putting a bandage on it, it will not solve the problem, there is a reason why this is happening, if you are happening to use OkHTTP you will find that this line

 override fun intercept(chain: Interceptor.Chain): Response {
       var request = chain.request()
       ...
}

Excecutes an internal proceed method inside the okHttp library, this proceed method throws an IOException

interface Chain {
    fun request(): Request

    @Throws(IOException::class)
    fun proceed(request: Request): Response

    /**
     * Returns the connection the request will be executed on. This is only available in the chains
     * of network interceptors; for application interceptors this is always null.
     */
    fun connection(): Connection?

    fun call(): Call

 ...

To solve this issue, you must run this on a try catch function and return a mocked response error code with the message, so the team working behind of it can access its error and debug easily, instead of crashing the user app.

override fun intercept(chain: Interceptor.Chain): Response {
        return try {
            
         var request = chain.request()

        } catch(e: IOException) {
          
            Response.Builder()
            .code(500)
            .message("Request failed with: $e.message")
            .build()
}

Doing so you can catch any IOException, SocketTiemoutException is one of them, but it could be any in the future.

1 Comment

How we can test this case?
1
If you are using Retrofit and Kotlin then use following code:
    var BASE_URL:String="Your URL"
    val clientSetup = OkHttpClient.Builder()
        .connectTimeout(1, TimeUnit.MINUTES)
        .writeTimeout(1, TimeUnit.MINUTES) // write timeout
        .readTimeout(1, TimeUnit.MINUTES) // read timeout
        .build()

    val getClientApi: ApiInterface
        get() {
            var retrofit: Retrofit =  Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(clientSetup)
                .build()
        }

2 Comments

This one helped me but can you please tell what is default time set for timeout? and is there any other clean method to avoid this problem?
normally http requests will not take that longer like 1 minute. Its better to fail and retry than increase timeout drastically. it will only increase the avg success time
0

In my case adding ping interval to OkHttp helps a lot in reducing number of SocketTimeoutExceptions in the app.

OkHttpClient.Builder()
        .pingInterval(3, SECONDS)
        .build()

but i am not sure if these timeouts were related to request size. I mentioned it also in this issue on github reported to OkHttp library

Comments

-1

Run into a Run Catching

runCatching {
       service
}
 .map {
       if (it.isSuccessful && it.body() != null) {
           Success(Unit)
       } else {
           Error(Failure.AuthError.error(it.errorBody()))
       }
}
 .getOrElse {
       Error(Failure.Throwable(it))
}

Comments

-2

Check if your url is correct. This error can be because of wrong url line

1 Comment

What if server down? Then it behaves same like wrong URL as response won't be arriving from server. So setting proper URL is not the solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.