scalabeginner
Exception Handling Patterns
Handle exceptions in Scala: try-catch-finally, Try monad, NonFatal, and custom exceptions.
scalaPress ⌘/Ctrl + Shift + C to copy
import scala.util.{Try, Success, Failure, Using}
import scala.util.control.NonFatal
// Custom exceptions
class AppException(message: String, cause: Throwable = null)
extends RuntimeException(message, cause)
class NotFoundException(entity: String, id: String)
extends AppException(s"$entity not found: $id")
class ValidationException(field: String, reason: String)
extends AppException(s"Validation failed for $field: $reason")
// Basic try-catch-finally
def parseNumber(s: String): Int =
try
s.toInt
catch
case e: NumberFormatException =>
println(s"Cannot parse '$s': ${e.getMessage}")
0
finally
println(s"Attempted to parse: $s")
// Using Try monad
def safeDivide(a: Double, b: Double): Try[Double] =
Try(a / b).filter(d => !d.isInfinite && !d.isNaN)
def loadConfig(path: String): Try[Map[String, String]] = Try {
val source = scala.io.Source.fromFile(path)
try
source.getLines()
.filter(_.contains("="))
.map { line =>
val Array(k, v) = line.split("=", 2)
k.trim -> v.trim
}
.toMap
finally
source.close()
}
// Chaining Try operations
def processData(input: String): Try[String] =
for
num <- Try(input.toInt)
result <- safeDivide(100.0, num)
output <- Try(f"Result: $result%.4f")
yield output
// NonFatal matcher (catches everything except fatal errors)
def safeExecute[T](block: => T): Either[String, T] =
try Right(block)
catch case NonFatal(e) => Left(s"${e.getClass.getSimpleName}: ${e.getMessage}")
// Retry pattern
def withRetry[T](maxAttempts: Int, delay: Long = 100)(block: => T): Try[T] =
var lastError: Throwable = null
for attempt <- 1 to maxAttempts do
try return Success(block)
catch
case NonFatal(e) =>
lastError = e
println(s"Attempt $attempt/$maxAttempts failed: ${e.getMessage}")
if attempt < maxAttempts then Thread.sleep(delay)
Failure(lastError)
@main def run(): Unit =
// Basic
println(s"Parse '42': ${parseNumber("42")}")
println(s"Parse 'abc': ${parseNumber("abc")}")
println()
// Try monad
println(s"10/3: ${safeDivide(10, 3)}")
println(s"10/0: ${safeDivide(10, 0)}")
// Chain
println(processData("4"))
println(processData("0"))
println(processData("abc"))
// Recovery
val recovered = processData("abc").recover {
case _: NumberFormatException => "Default: 0"
}
println(s"Recovered: $recovered")
// Pattern matching on Try
processData("5") match
case Success(v) => println(s"Success: $v")
case Failure(e) => println(s"Failed: ${e.getMessage}")
// NonFatal
println(safeExecute(42 / 0))
println(safeExecute("hello".toInt))
// Custom exceptions
try
throw NotFoundException("User", "42")
catch
case e: NotFoundException => println(s"Caught: ${e.getMessage}")
case e: AppException => println(s"App error: ${e.getMessage}")Use Cases
- Graceful error recovery
- File and network error handling
- Retry logic for flaky operations
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
scalaintermediate
Option Either and Try Error Handling
Handle errors functionally with Option, Either, and Try: map, flatMap, recover, and for-comprehensions.
Best for: Null-safe programming with Option
#scala#option
javaintermediate
Custom Exception Hierarchy
Design a clean exception hierarchy with custom exceptions, error codes, and exception mapping.
Best for: Consistent error handling across services
#java#exceptions
scalabeginner
Scala Hello World Application
Create a basic Scala application with main method, string interpolation, and val/var basics.
Best for: Getting started with Scala
#scala#basics
scalabeginner
Pattern Matching Fundamentals
Use Scala pattern matching with guards, type patterns, tuple patterns, and nested extractors.
Best for: Control flow with pattern matching
#scala#pattern-matching