Are you struggling with TimeoutException
in your Kotlin API calls? This common issue often occurs when making network requests with Retrofit or OkHttp that take too long to respond. In this guide, you’ll learn how to properly handle timeouts in Kotlin-based Android projects by configuring timeouts correctly and using coroutine best practices.

What Causes TimeoutException?
A TimeoutException
usually appears when your API call exceeds the default timeout duration. This is particularly common on slow networks or large payloads. To fix it, you can:
- Set custom timeout values in OkHttpClient.
- Handle exceptions gracefully in
try-catch
. - Implement fallback mechanisms.
Sample Fix using Retrofit + Coroutine
1. API Client Configuration (with custom timeout)
// ApiClient.kt import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import java.util.concurrent.TimeUnit object ApiClient { private const val BASE_URL = "https://jsonplaceholder.typicode.com/" private val client = OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build() val instance: ApiService by lazy { Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService::class.java) } }
2. Define Your API Interface
// ApiService.kt import retrofit2.http.GET interface ApiService { @GET("posts") suspend fun getPosts(): List<Post> }
3. Data Model
// Post.kt data class Post( val userId: Int, val id: Int, val title: String, val body: String )
4. Repository with Coroutine Exception Handling
// PostRepository.kt import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.net.SocketTimeoutException class PostRepository { suspend fun fetchPosts(): Result<List<Post>> { return withContext(Dispatchers.IO) { try { val posts = ApiClient.instance.getPosts() Result.success(posts) } catch (e: SocketTimeoutException) { Result.failure(Exception("Request timed out. Please try again.")) } catch (e: Exception) { Result.failure(e) } } } }
5. Using in ViewModel
// PostViewModel.kt import androidx.lifecycle.ViewModel import androidx.lifecycle.liveData class PostViewModel : ViewModel() { private val repository = PostRepository() val posts = liveData { val result = repository.fetchPosts() emit(result) } }
External Reference
Learn more about timeout configuration in OkHttp official documentation.