The 0__ answer is good, but it would be better if you were not forced to write a specific object ( CausedByFoo ) for each potential exception. As it happens, there is nothing to change to get a common CausedBy helper object:
class Foo(message: String) extends Exception(message) class Bar(cause: Throwable) extends Exception(cause) object CausedBy { def unapply(e: Throwable): Option[Throwable] = Option(e.getCause) } def test(block: => Unit): String = try { block "ok" } catch { case CausedBy(ex: Foo) => "not ok: " + ex.getMessage } test(println("hello")) test(println("hello".toInt)) // uncaught exception test(throw new Bar(new Foo("Ooops, foo error!"))) // caught
As should be obvious, you can use CausedBy with any exception (for example, by running case CausedBy(ex: Baz) .
You can even nest it to handle an exception caused by an exception caused by an exception (by doing something like case CausedBy(CausedBy(ex: Foo))
source share