Skip to main content

AppException

Sealed exception hierarchy providing typed error handling across all layers of the application.

Module: :core

Definition

sealed class AppException(message: String?) : Exception(message) {
class NetworkException(message: String?) : AppException(message)
class TimeoutException(message: String?) : AppException(message)
class UnauthorizedException(message: String?) : AppException(message)
class ForbiddenException(message: String?) : AppException(message)
class NotFoundException(message: String?) : AppException(message)
class ServerException(val code: Int, message: String?) : AppException(message)
class UnknownException(cause: Throwable?) : AppException(cause?.message)
}

Exception Types

TypeHTTP StatusWhen
NetworkExceptionNo internet / connection refused
TimeoutExceptionRequest timed out
UnauthorizedException401Invalid or expired token
ForbiddenException403Insufficient permissions
NotFoundException404Resource not found
ServerException5xxServer error (code is preserved)
UnknownExceptionCatch-all for unexpected errors

Pattern Matching

when (exception) {
is AppException.UnauthorizedException -> {
// Token expired — navigate to login
navigateToLogin()
}
is AppException.NetworkException -> {
// No connectivity
showOfflineMessage()
}
is AppException.ServerException -> {
// Server error with status code
showServerError("Server error: ${exception.code}")
}
is AppException.TimeoutException -> {
showRetryDialog()
}
is AppException.NotFoundException -> {
showNotFound()
}
is AppException.ForbiddenException -> {
showPermissionDenied()
}
is AppException.UnknownException -> {
showGenericError(exception.message)
}
}

Usage with BaseViewModel

In execute() and collect(), the onError reducer receives AppException:

fun loadProducts() = execute(
call = { getProductsUseCase() },
onSuccess = { copy(products = it) },
onError = { exception ->
when (exception) {
is AppException.UnauthorizedException -> copy(needsLogin = true)
else -> copy(error = exception.message)
}
},
errorEvent = { exception ->
ProductEvent.ShowError(exception.message ?: "Something went wrong")
}
)

Automatic Mapping

The :network module's safeApiCall automatically maps HTTP responses and Ktor exceptions to AppException. You never need to create these exceptions manually when using ApiService.