title: Handling http errors in retrofit and okhttp in android application
body: <p>In my android application I have used retrofit and okhttp as shown in below code snippets. The application works well and I am not getting any error during testing and also on production but some times  <strong>socket timeout exception</strong>, <strong>sslhandshake exceptions</strong>, <strong>unknown host exceptions</strong> are being logged in by firebase crashalytics  as fatal exceptions, which means that application is being crashed when these exceptions are thrown. I have checked with our network team and they have double checked every thing at their end, but issue is still there.  Is there a way that I can catch all these exceptions to avoid any fatal crashes. Here is my implementaion</p>
  
  <pre><code>class CoreDataModule {
  
      @Provides
      fun provideOkHttpClient(): OkHttpClient {
          val interceptor = HttpLoggingInterceptor()
          interceptor.level = HttpLoggingInterceptor.Level.BODY
          val client = OkHttpClient().newBuilder()
              .connectTimeout(15, TimeUnit.SECONDS)
              .readTimeout(90, TimeUnit.SECONDS)
              .writeTimeout(60, TimeUnit.SECONDS)
          if (BuildConfig.DEBUG) {
              client.addInterceptor(interceptor)
          }
          client.addInterceptor { chain -&gt;
              val request = chain.request()
              val response = chain.proceed(request)
              response
          }
          return client.build()
      }
  
  
      @Provides
      @Singleton
      fun provideMoshi(): Moshi = Moshi.Builder().build()
  
      @Provides
      @Singleton
      fun provideMoshiConverterFactory(): MoshiConverterFactory =
          MoshiConverterFactory.create()
  }
  </code></pre>
  
  <p>This is inside Appmodule class</p>
  
  <pre><code>@Singleton
      @Provides
      fun providemyappService(@appAPI okHttpClient: OkHttpClient, converterFactory: MoshiConverterFactory) =
          provideService(okHttpClient, converterFactory, myappApi::class.java)
  
  
      @appAPI
      @Provides
      fun providePrivateOkHttpClient(upstreamClient: OkHttpClient): OkHttpClient {
          return upstreamClient.newBuilder().build()
      }
  
  
      @Singleton
      @Provides
      fun provideRemoteDataSource(myappService: myappApi) = RemoteDataSource(myappService)
  
  private fun createRetrofit(
          okhttpClient: OkHttpClient,
          converterFactory: MoshiConverterFactory
      ): Retrofit {
          return if (BuildConfig.DEBUG) {
              Retrofit.Builder()
                  .baseUrl(BASE_URL_STAGE)
                  .client(okhttpClient)
                  .addConverterFactory(converterFactory)
                  .build()
          } else {
              Retrofit.Builder()
                  .baseUrl(BASE_URL)
                  .client(okhttpClient)
                  .addConverterFactory(converterFactory)
                  .build()
          }
      }
  
      private fun &lt;T&gt; provideService(
          okhttpClient: OkHttpClient,
          converterFactory: MoshiConverterFactory, clazz: Class&lt;T&gt;
      ): T {
          return createRetrofit(okhttpClient, converterFactory).create(clazz)
      }
  </code></pre>
  
  <p>This is inside API end point interface</p>
  
  <pre><code>@POST("Validate/UserValidation")
      @FormUrlEncoded
      suspend fun validateUser(@Field("data") data: String): Response&lt;ValidationResponse&gt;
  </code></pre>
  
  <p>Here are some crash logs from firebase console</p>
  
  <pre><code>Fatal Exception: java.net.SocketTimeoutException: failed to connect to app.com.pk/123.123.123.124 (port 443) after 15000ms
         at libcore.io.IoBridge.connectErrno(IoBridge.java:191) (Note: Actual fqdn and ip replaced here)
         at libcore.io.IoBridge.connect(IoBridge.java:127)
         at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:201)
         at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:520)
         at java.net.Socket.connect(Socket.java:927)
         at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.java:73)
         at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:246)
         at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:166)
         at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
         at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
         at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
         at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
         at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
         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)
  </code></pre>
  
  <p>This is another stacktrace</p>
  
  <pre><code>Fatal Exception: java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
         at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:629)
         at libcore.io.IoBridge.recvfrom(IoBridge.java:591)
         at java.net.PlainSocketImpl.read(PlainSocketImpl.java:487)
         at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
         at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
         at okio.Okio$2.read(Okio.java:140)
         at okio.AsyncTimeout$2.read(AsyncTimeout.java:237)
         at okio.RealBufferedSource.indexOf(RealBufferedSource.java:358)
         at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:230)
         at okhttp3.internal.http1.Http1Codec.readHeaderLine(Http1Codec.java:215)
         at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189)
         at okhttp3.internal.connection.RealConnection.createTunnel(RealConnection.java:376)
         at okhttp3.internal.connection.RealConnection.connectTunnel(RealConnection.java:219)
         at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:160)
         at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
         at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
         at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
         at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
         at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
         at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
  </code></pre>
  
  <p>SSL Handshake exception</p>
  
  <pre><code>Fatal Exception: javax.net.ssl.SSLHandshakeException: SSL handshake aborted: ssl=0x7fa29fd100: I/O error during system call, Connection reset by peer
         at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(NativeCrypto.java)
         at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:323)
         at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:319)
         at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:283)
         at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:168)
         at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
         at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
         at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
         at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
         at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
         at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
         at java.lang.Thread.run(Thread.java:818)
  </code></pre>
  
  <p>Unknown host exception</p>
  
  <pre><code>Fatal Exception: java.net.UnknownHostException: Unable to resolve host "app.com.pk": No address associated with hostname Note:ACtual FQDN changed here
         at java.net.InetAddress.lookupHostByName(InetAddress.java:424)
         at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
         at java.net.InetAddress.getAllByName(InetAddress.java:214)
         at okhttp3.Dns$1.lookup(Dns.java:40)
         at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:185)
         at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.java:149)
         at okhttp3.internal.connection.RouteSelector.next(RouteSelector.java:84)
         at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:214)
         at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
         at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
         at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
         at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
         at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
         at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
         at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
         at java.lang.Thread.run(Thread.java:856)
  </code></pre>
  
  <p>I am using retrofit_version = "2.6.0"</p>