Skip to content
tezvyn:

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

Source: developer.android.comMediumHow cards are made

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

Structured error handling in coroutines and mapping exceptions to recovery.

Key points

Catch IOException for connectivity and HttpException for HTTP errors; wrap in a sealed Result.

Watch out for

Catching Exception or exposing raw errors to UI.

What's really being asked

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.

The full answer

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.

The mistakes people make

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.

What usually comes next

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?

A 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.

Interview question

Which strategy correctly distinguishes network connectivity failures from HTTP server errors in a suspend repository function while keeping the UI independent of Retrofit?

  • a.Catch IOException and HttpException in the repository, map them to sealed Result types, and return those to the ViewModelCorrect
  • b.Return Retrofit's raw Response wrapper to the ViewModel and inspect HTTP status codes directly in the UI
  • c.Let IOException and HttpException propagate to the ViewModel and use a CoroutineExceptionHandler to choose the error UI
  • d.Catch generic Exception in the repository and emit a single Failure state for the ViewModel to display
Why?

Mapping specific exceptions to domain Result types in the repository prevents low-level networking details from leaking into the UI and enables differentiated recovery. Option C is tempting but wrong because CoroutineExceptionHandler is designed for uncaught exceptions in a scope, not for structured business-logic error handling.

Just read this? Test yourself on what you have been reading.

Read the original → developer.android.com

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on kotlin — each one lists the topics its interview covers.

See open roles