❗ 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 :
