mirosval mirosval - 4 months ago 16
Scala Question

How to determine if exception was caused by a specific other exception?

Elastic search throws RemoteTransportException that is caused by IndexAlreadyExists exception.

I would like to ignore this one case, but still make sure to catch any other exceptions that might occur.

To that end, I implemented a function to determine if an exception was caused by another exception:

private def exceptionCausedBy[T](e: Throwable): Boolean = {
// scalastyle:off null
e.isInstanceOf[T] || (e.getCause != null && exceptionCausedBy[T](e.getCause))
}


which I call like so:

...
case e: Throwable if exceptionCausedBy[IndexAlreadyExistsException](e) =>
...


This, however gives warning:

abstract type T is unchecked since it is eliminated by erasure
e.isInstanceOf[T] || (e.getCause != null && exceptionCausedBy[T](e.getCause))
^


Which makes sense, because the type T is known at compile time and erased by the compiler.

Is it sufficient to add ClassTag like so?

def exceptionCausedBy[T: ClassTag](e: Throwable): Boolean = {
// scalastyle:off null
e.isInstanceOf[T] || (e.getCause != null && exceptionCausedBy[T](e.getCause))
}


My testing in IDEA Scratchfile seems to confirm this, but I would like to get some expert opinion.

Also if this is a totally stupid way of going about this, please don't hesitate to point it out :)

Answer

isInstanceOf[T] check doesn't use ClassTag, matching : T does. So it should be

def exceptionCausedBy[T: ClassTag](e: Throwable): Boolean = e match {
  // scalastyle:off null
  case null => false
  // scalastyle:on null
  case _: T => true
  case _ => exceptionCausedBy[T](e.getCause)
}