In the previous blog ZIO Effects: How to Handle Errors? we have learned about How ZIO provides various means to handle and respond to failures.
In addition to this blog, we will see all the ways to handle the exceptions with its Implementation.
Either
- If the effect fails, the result is in the form of
Left
- If the effect succeeds, the result is in the form of
Right
Code Implementation with Example
import zio.{ExitCode, URIO, ZIO}
object HandlingExceptionUsingEither extends zio.App {
val zEither: URIO[Any, Either[String, Nothing]] = ZIO.fail("I am failing you.").either
val zMatch: ZIO[Any, Nothing, String] = zEither.map {
case Right(success) => success
case Left(exception) => s"Oops it failed with an exception: $exception"
}
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
(for {
value <- zMatch
_ <- zio.console.putStrLn(value)
} yield ()).exitCode
}
}
Output:
Oops it failed with an exception: I am failing you.

Catching All Errors
This method is used to handle all the exceptions which might crash the program inappropriately.
Code Implementation with Example
import zio.{ExitCode, IO, URIO, ZIO}
object HandlingExceptionUsingCatchAll extends zio.App {
val zFailed: IO[String, Nothing] = ZIO.fail("Some failure")
val zCatchAll: ZIO[Any, Nothing, String] = zFailed.catchAll { _ =>
ZIO.succeed("I will catch you from fail.")
}
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
(for {
value <- zCatchAll
_ <- zio.console.putStrLn(value)
} yield ()).exitCode
}
}
Output:
I will catch you from fail.

Catching Some Errors
This method is used when we want to handle any specific type of exception.
Code Implementation with Example
import zio.{ExitCode, IO, URIO, ZIO}
import java.io.FileNotFoundException
import scala.io.{BufferedSource, Source}
object HandlingExceptionUsingCatchSome extends zio.App {
val FileReader: ZIO[Any, Throwable, BufferedSource] = IO(Source.fromFile("PrimaryFile.txt")).catchSome {
case _: FileNotFoundException => IO(Source.fromFile("BackUpFile.txt"))
}
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
(for {
source <- FileReader
value <- IO(source.getLines().mkString("\n"))
_ <- zio.console.putStrLn(value)
} yield ()).exitCode
}
}
Output:
Hi, This is Back up File.

Fallback
This method is used when we have to provide a backup. For example: Suppose I want to read a file “Primary.txt” but it is not available, So I will provide a backup as “Backup.txt”. Therefore, If the Primary file is not available use the Backup file.
Code Implementation with Example
import zio.{ExitCode, IO, URIO}
import scala.io.Source
object HandlingExceptionUsingOrElse extends zio.App{
val fileReader = IO(Source.fromFile("Primary.txt")).orElse(IO(Source.fromFile("BackUpFile.txt")))
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
(for{
source <- fileReader
value <- IO(source.getLines().mkString("\n"))
_ <- zio.console.putStrLn(value)
}yield ()).exitCode
}
}
Output:
Hi, This is Back up File.

Retrying
However, there are a number of useful methods on the ZIO data type for retrying failed effects.
This method is used to give some try before handling the exception. For example, in many cases program might take a few milliseconds to execute that piece of code which might fail in the first attempt but in another attempt might lead to success. However, If it still fails then we can handle it with any other method which is mentioned above.
Code Implementation with Example
import zio.{ExitCode, IO, URIO, ZIO}
import scala.io.{BufferedSource, Source}
object HandlingExceptionUsingRetry extends zio.App {
val fileReader: ZIO[Any, Throwable, BufferedSource] = {
IO(Source.fromFile("Primary.txt"))
.retryN(3)
.orElse(IO(Source.fromFile("BackUpFile.txt")))
}
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
(for{
source <- fileReader
value <- IO(source.getLines().mkString("\n"))
_ <- zio.console.putStrLn(value)
}yield ()).exitCode
}
}
Output:
Hi, This is Back up File.

Conclusion
Thank you guys for making it to the end of the blog I hope you gained some knowledge about How to handle exceptions along with their Implementation.
Reference
For more detailed information you can use this link: https://zio.dev/