Search code examples
androidcoroutinesocket-timeout-exception

Kotlin Coroutine : How to catch SocketTimeout Exception in Interceptor


I just started using coroutines for 2 async calls that run in parallel . One of the aync task makes a service call. This service can sometimes take a long time to respond. In this case my code is crashing in my dagger injected Interceptor function. I've tried to catch the error and throw it back to my coroutine but its never caught.

Coroutine:

    try {
                CoroutineScope(Dispatchers.IO).launch {

                    val deferredList = listOf(async {

                        myAPI?.getAllMarks(WebService.getAwsAccessToken(),
                                UserInfoManager?.userInfo?.guid)

                    }, async {

                        getClassFromJsonFile(R.raw.temp_whatsnew, WhatsNew::class.java)
                    })

                    var theList: List<Any> =
                            deferredList.awaitAll() // wait for all data to be processed without blocking the UI thread

                    withContext(Dispatchers.Main) {
                        mListener?.onWhatsNewDownloaded(theList.get(1) as WhatsNew,
                                theList.get(0) as List<Coachmark>)
                    }
                }
            } catch (t: Throwable) {
  //exception never reaches here!              
Log.v(WhatsNewInteractorImpl::class.java.simpleName, t.localizedMessage)

            }

Interceptor:

try {
                response = chain.proceed(newRequest);
            } catch (SocketTimeoutException e) {
               //CRASHES HERE!
              throw new SocketTimeoutException("socket timeout");
            }

Solution

  • You need a CoroutineExceptionHandler:

    private val coroutineExceptionHandler = CoroutineExceptionHandler{_ , throwable -> 
      //handle error here
    }
    
    someScope.launch(Dispatchers.IO + coroutineExceptionHandler){
    
    }
    

    And I suggest not to surround with try and catch outside of a coroutine because the exception could be thrown from inside of it.

    Other options:

    scope.launch(Dispatchers.IO){
      try{
       //throwable operation
      }catch(e: SocketTimeOutException){
    
       }
    }
    

    Or you can just forget about an error handling, and implement coroutines method withTimeOut