192
try { } catch (ex: MyException1, MyException2 ) { logger.warn("", ex) } 

or

try { } catch (ex: MyException1 | MyException2 ) { logger.warn("", ex) } 

As a result, a compilation error: Unresolved reference: MyException2.

How can I catch many exceptions at the same time on Kotlin?

0

5 Answers 5

226

Update: Vote for the following issue KT-7128 if you want this feature to land in Kotlin. Thanks @Cristan

According to this thread this feature is not supported at this moment.

abreslav - JetBrains Team

Not at the moment, but it is on the table

You can mimic the multi-catch though:

try { // do some work } catch (ex: Exception) { when(ex) { is IllegalAccessException, is IndexOutOfBoundsException -> { // handle those above } else -> throw ex } } 
Sign up to request clarification or add additional context in comments.

10 Comments

I'm copying pdvrieze reply here: This certainly works, but is slightly less efficient as the caught exception is explicit to the jvm (so a non-processed exception will not be caught and rethrown which would be the corollary of your solution)
@IARI The else clause rethrows the unwanted exception.
Even if you throw away the arguments of elegance and ugliness aside, Kotlin (which claims to be concise) is actually 2x as verbose as Java in this case
That gets flagged by Detekt because you're catching too generic an exception ;-)
|
17

To add to miensol's answer: although multi-catch in Kotlin isn't yet supported, there are more alternatives that should be mentioned.

Aside from the try-catch-when, you could also implement a method to mimic a multi-catch. Here's one option:

fun (() -> Unit).catch(vararg exceptions: KClass<out Throwable>, catchBlock: (Throwable) -> Unit) { try { this() } catch (e: Throwable) { if (e::class in exceptions) catchBlock(e) else throw e } } 

And using it would look like:

fun main(args: Array<String>) { // ... { println("Hello") // some code that could throw an exception }.catch(IOException::class, IllegalAccessException::class) { // Handle the exception } } 

You'll want to use a function to produce a lambda rather than using a raw lambda as shown above (otherwise you'll run into "MANY_LAMBDA_EXPRESSION_ARGUMENTS" and other issues pretty quickly). Something like fun attempt(block: () -> Unit) = block would work.

Of course, you may want to chain objects instead of lambdas for composing your logic more elegantly or to behave differently than a plain old try-catch.

I would only recommend using this approach over miensol's if you are adding some specialization. For simple multi-catch uses, a when expression is the simplest solution.

5 Comments

If I understand it correctly you pass classes in your catch, but param exceptions takes objects.
you're awesome man @aro, thanks for providing this alternative
This alternative is good, thanks Aro :) Better than nothing. However, I hope they will get to that feature although my issue KT-7128 was opened 5 years ago :-)
Could you maybe change your example? I have zero clue how to call this function. I am trying fun test() { myExceptionCode }.catch() but it does not work
@Andrew I'll look at changing it soon. It concerns me a bit that people are trying to use it raw. It's meant as a proof of concept to give people a starting point to write their own helper functions. It definitely needs to be cleaned up--mainly removing the lambda extension since that is probably a point of confusion.
1

The example from aro is very good but if there are inheritances, it won't work like in Java.

Your answer inspired me to write an extension function for that. To also allow inherited classes you have to check for instance instead of comparing directly.

inline fun multiCatch(runThis: () -> Unit, catchBlock: (Throwable) -> Unit, vararg exceptions: KClass<out Throwable>) { try { runThis() } catch (exception: Exception) { val contains = exceptions.find { it.isInstance(exception) } if (contains != null) catchBlock(exception) else throw exception }} 

To see how to use, you can have a look in my library on GitHub here

1 Comment

What's the reason of "-1"? try { ... } catch (X | Y e) { ... } in Java also checks the inheritance. This answer mimics the Java's behaviour, it's more convenient for example for catching IOException with many different subtypes.
1

This way you can take multiple Catch and with the MultiCatch method you can detect Exceptions

import kotlin.reflect.KClass import kotlin.reflect.full.isSubclassOf class NegetiveNumber : Exception() class StringFalse : Exception() fun <R> Exception.multiCatch(vararg classes: KClass<*>, block: () -> R): R { return if (classes.any { this::class.isSubclassOf(it) }) block() else throw this } class Human() { var name = "" set(name) { if (name.isEmpty()) { throw StringFalse() } else { field = name } } var age = 0 set(age) { if (age <= 0) { throw NegetiveNumber() } else { field = age } } } fun main() { val human = Human() human.name = "Omidreza" human.age = 0 try { println(human.name) println(human.age) } catch (e: Exception) { e.multiCatch(NegetiveNumber::class, StringFalse::class) { println(e.message) } }finally { println("end") } } 

this is multiCatch():

fun <R> Exception.multiCatch(vararg classes: KClass<*>, block: () -> R): R { return if (classes.any { this::class.isSubclassOf(it) }) block() else throw this } 

Comments

-1

In Kotlin you can do this:

try{ } catch(e: MyException1){ } catch(e: MyException2){ } catch(e: MyException3){ } [...] 

6 Comments

This is obvious but it requires you to have separate catch block for each exception. However the idea of multi-catching is to have single catch block for a set of exceptions
True but it's no worse than the other answers on this question. What a massive oversight in the language.
It is obviously worse because it doesn't answer the question at all.
The question is "How to catch many exceptions at the same time in Kotlin?". This answers how do do that. This answer is actually is a better answer because it avoids broad exception catching like e: Exception. This is the way language designed.
@Sermilion And when I want to do the same thing for multiple exceptions, what would you like me to do? Extract a function and copy it into each catch block? Create some convoluted utility function to implement multicatch myself? Verbosely catch the base Exception and when over each type? In no way shape or form is disabling the ability to multicatch in a language that uses try-catch blocks a good design.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.