Kotlin – Custom Exceptions: Define Your Own Error Types
Introduction – Why Learn Kotlin Custom Exceptions?
While Kotlin provides standard exceptions like IllegalArgumentException, sometimes you need to represent domain-specific error scenarios. That’s where custom exceptions come in—they help you create semantic, reusable, and testable error-handling logic tailored to your app’s needs.
In this guide, you’ll learn:
- How to create and use custom exceptions
- When to prefer a custom exception over built-in ones
- How to inherit from the right base class (
Exception,RuntimeException) - Best practices and real-world use cases
Defining a Simple Custom Exception
class InvalidUserInputException(message: String) : Exception(message)
✔️ This class inherits from Kotlin’s standard Exception class and can carry a custom message.
Throwing Your Custom Exception
fun validateUsername(username: String) {
if (username.isBlank()) {
throw InvalidUserInputException("Username must not be blank")
}
}
Usage:
try {
validateUsername(" ")
} catch (e: InvalidUserInputException) {
println("Caught: ${e.message}")
}
Output:
Caught: Username must not be blank
Custom Exception with Additional Fields
You can add more context to your exception:
class ApiException(val errorCode: Int, message: String) : Exception(message)
Usage:
throw ApiException(404, "Resource not found")
✔️ Helps carry structured data through exceptions.
Runtime vs Checked Exceptions in Kotlin
Kotlin doesn’t enforce checked exceptions. You can choose:
Exception(checked in Java) → For recoverable errorsRuntimeException→ For programming errors (likeNullPointerException)
class DatabaseException(message: String) : RuntimeException(message)
✔️ Use RuntimeException when it’s the developer’s fault, and Exception for external/environmental issues.
Inheritance Hierarchy
Custom exceptions can inherit from each other to create a structured exception system:
open class AppException(message: String) : Exception(message)
class AuthException(message: String) : AppException(message)
class NetworkException(message: String) : AppException(message)
✔️ Use parent classes to catch broad errors, and child classes for specific handling.
Catching Multiple Custom Exceptions
try {
throw AuthException("Unauthorized")
} catch (e: AuthException) {
println("Auth error: ${e.message}")
} catch (e: AppException) {
println("General app error")
}
Common Mistakes
| Mistake | Fix |
|---|---|
Extending Throwable directly | Extend from Exception or RuntimeException instead |
| Not adding meaningful error messages | Always include a message for better debugging |
| Swallowing custom exceptions silently | Log or rethrow them with context |
| Using generic exceptions everywhere | Define custom types for clear and semantic code |
Best Practices for Kotlin Custom Exceptions
| Practice | Benefit |
|---|---|
Extend Exception or RuntimeException | Aligns with platform expectations |
| Use specific names and messages | Makes debugging and logging easier |
| Organize in a base exception hierarchy | Enables flexible exception catching strategies |
| Use for domain-level errors | Improves clarity in service/business layer logic |
Summary – Recap & Next Steps
Custom exceptions let you define tailored error types that improve code clarity, debuggability, and modularity. Kotlin makes it easy to define and use them, even without checked exceptions.
Key Takeaways:
- Create a custom exception using
class MyException : Exception(...) - Use
RuntimeExceptionfor programming logic errors,Exceptionfor external errors - Add fields or base classes for structured error handling
- Combine with
throw,try-catch, and@Throwsas needed
Practical Use:
Custom exceptions are ideal for API failure handling, form validation, business rule violations, and error modeling in layered architecture.
FAQs – Kotlin Custom Exceptions
How do I define a custom exception in Kotlin?
Inherit from Exception or RuntimeException:
class MyException(message: String) : Exception(message)
Should I use Exception or RuntimeException?
Use RuntimeException for logic bugs (nulls, illegal states). Use Exception for environmental or recoverable issues.
Can I pass extra data in a custom exception?
Yes. Add properties to your class:
class ApiError(val code: Int, message: String) : Exception(message)
Can I catch custom exceptions using their parent class?
Yes. You can create an exception hierarchy and catch using the base type.
Do custom exceptions work with Java code?
Yes. If you’re exposing them to Java, annotate with @Throws(ExceptionType::class) if needed.
Share Now :
