How do you differentiate network and server errors in suspend functions?

Structured error handling in coroutines and mapping exceptions to recovery.
Catch IOException for connectivity and HttpException for HTTP errors; wrap in a sealed Result.
Catching Exception or exposing raw errors to UI.
WHAT THIS TESTS: This question probes whether you treat exceptions as domain modeling problems rather than implementation accidents. The interviewer wants to see that you distinguish transient infrastructure failures from business-logic failures, and that you prevent low-level networking details from leaking into ViewModels or UI code.
A GOOD ANSWER COVERS: First, specific exception types. You should mention catching IOException for connectivity issues such as timeouts, DNS failures, or airplane mode, and catching HttpException for non-2xx HTTP responses like 404 or 500. Second, mapping to a sealed class. You should describe wrapping these exceptions into a domain Result type such as NetworkError, ServerError, or UnknownError so that presentation layers remain independent of Retrofit or OkHttp. Third, differentiated handling. You should explain that connectivity errors might trigger a retry with exponential backoff or an offline banner, while server errors might show a user message, log an incident identifier, or fail fast depending on the status code. Fourth, coroutine scope awareness. You should note that structured concurrency means exceptions propagate up the Job hierarchy, so catching should happen inside the repository or use case, not be deferred to a global handler unless for crash reporting.
COMMON WRONG ANSWERS: Catching generic Exception and treating all failures identically. Exposing Retrofit's HttpException or OkHttp's IOException directly to a ViewModel or Composable. Suggesting infinite retries without backoff for every error type. Claiming that CoroutineExceptionHandler is the right place to fix user-facing recovery logic, when it is actually meant for uncaught exceptions in a scope. Ignoring that HttpException contains a response code that should drive different behavior for 401 versus 500.
LIKELY FOLLOW-UPS: How would you test this error mapping without making real network calls? What would you do for a 401 Unauthorized versus a 403 Forbidden? How do you handle cancellation exceptions if the user leaves the screen mid-request? Where do you place the retry logic, and how do you avoid retrying on 4xx client errors?
ONE CONCRETE EXAMPLE: In a repository function suspended fun fetchProfile(): Result<Profile>, you wrap the Retrofit call in a try-catch. The catch block for IOException returns Result.Error(NetworkError.NoConnection). The catch block for HttpException inspects code(): if it is 404 you return Result.Error(ServerError.NotFound), if it is 500 you return Result.Error(ServerError.Internal), and otherwise you return Result.Error(ServerError.Unknown). The ViewModel consumes only the Result type and shows a full-screen error for NetworkError while showing a toast for ServerError.Internal.
Read the original → developer.android.com
- #kotlin
- #coroutines
- #error-handling
- #retrofit
- #android
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.