codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🎯

Kotlin

28 / 68 topics
23Coroutines Basics24Suspend Functions25Channels in Coroutines26Flow in Kotlin27Concurrency Model28Exception Handling in Coroutines29Async and Await30Structured Concurrency
Tutorials/Kotlin/Exception Handling in Coroutines
🎯Kotlin

Exception Handling in Coroutines

Updated 2026-04-20
3 min read

Exception Handling in Coroutines

Exception handling is a critical aspect of any software development, ensuring that your application can gracefully handle unexpected situations and errors. In the context of coroutines, exception handling becomes even more important due to their asynchronous nature and the potential for multiple concurrent operations.

This tutorial will guide you through understanding how exceptions are handled in Kotlin coroutines, including best practices and real-world examples.

Introduction to Coroutines

Before diving into exception handling, let's briefly review what coroutines are. Coroutines are a language feature that allows you to write asynchronous code in a sequential manner, making it easier to read and maintain. They are particularly useful for I/O-bound and high-latency operations, such as network requests or file I/O.

Basic Exception Handling

In Kotlin, exceptions can be handled using try-catch blocks just like in regular synchronous code. However, when dealing with coroutines, there are additional considerations due to the asynchronous nature of coroutines.

Example: Basic Try-Catch in Coroutines

import kotlinx.coroutines.*

fun main() = runBlocking {
    try {
        launch {
            throw RuntimeException("Error occurred")
        }
    } catch (e: Exception) {
        println("Caught exception: ${e.message}")
    }
}

In this example, the launch function starts a new coroutine. If an exception is thrown inside the coroutine, it will be caught by the outer try-catch block.

CoroutineScope and Exceptions

When working with coroutines, you often use CoroutineScope. Understanding how exceptions are handled in different scopes is crucial.

Example: Exception Handling in CoroutineScope

import kotlinx.coroutines.*

fun main() = runBlocking {
    val scope = CoroutineScope(Dispatchers.Default)

    try {
        scope.launch {
            throw RuntimeException("Error occurred")
        }
    } catch (e: Exception) {
        println("Caught exception: ${e.message}")
    }

    // Ensure the scope is cancelled to prevent resource leaks
    scope.cancel()
}

In this example, the coroutine launched within CoroutineScope throws an exception. The outer try-catch block catches this exception. It's important to cancel the CoroutineScope after handling exceptions to free up resources.

SupervisorScope and Exception Handling

SupervisorScope is a special type of CoroutineScope that handles exceptions differently. Instead of cancelling all child coroutines when one throws an exception, it only cancels the failing coroutine.

Example: Using SupervisorScope

import kotlinx.coroutines.*

fun main() = runBlocking {
    val supervisorScope = SupervisorScope(Dispatchers.Default)

    supervisorScope.launch {
        throw RuntimeException("Error occurred")
    }

    supervisorScope.launch {
        println("This coroutine continues running")
    }
}

In this example, the first coroutine throws an exception. However, the second coroutine continues to run because SupervisorScope only cancels the failing coroutine.

Exception Propagation

Exceptions in coroutines can propagate up the call stack. Understanding how exceptions propagate is essential for effective error handling.

Example: Exception Propagation

import kotlinx.coroutines.*

fun main() = runBlocking {
    try {
        launch {
            throw RuntimeException("Error occurred")
        }
    } catch (e: Exception) {
        println("Caught exception: ${e.message}")
    }
}

In this example, the exception thrown in the coroutine is propagated to the outer try-catch block. This behavior can be controlled using CoroutineExceptionHandler.

CoroutineExceptionHandler

CoroutineExceptionHandler is a special type of Handler that allows you to handle exceptions globally for all coroutines within a scope.

Example: Using CoroutineExceptionHandler

import kotlinx.coroutines.*

fun main() = runBlocking {
    val handler = CoroutineExceptionHandler { _, exception ->
        println("Caught exception in handler: ${exception.message}")
    }

    val scope = CoroutineScope(Dispatchers.Default + handler)

    scope.launch {
        throw RuntimeException("Error occurred")
    }
}

In this example, the CoroutineExceptionHandler is added to the CoroutineScope. When an exception is thrown within the coroutine, it is caught by the handler.

Best Practices for Exception Handling in Coroutines

  1. Use SupervisorScope when appropriate: If you want some coroutines to continue running even if others fail, use SupervisorScope.
  2. Handle exceptions at the right level: Catch exceptions where they are most meaningful and relevant.
  3. Cancel CoroutineScopes properly: Always ensure that CoroutineScope is cancelled to prevent resource leaks.
  4. Use CoroutineExceptionHandler for global handling: For scenarios where you want a centralized exception handling mechanism, use CoroutineExceptionHandler.
  5. Avoid using try-catch in suspend functions: Instead, let exceptions propagate and handle them at the appropriate level.

Conclusion

Exception handling in coroutines is a powerful feature that allows you to build robust and resilient applications. By understanding how exceptions propagate and how different scopes handle them, you can effectively manage errors in your asynchronous code.

Remember to always use best practices for exception handling to ensure your application behaves predictably and efficiently even in the face of unexpected situations.


PreviousConcurrency ModelNext Async and Await

Recommended Gear

Concurrency ModelAsync and Await