ktorio / ktor

Framework for quickly creating connected applications in Kotlin with minimal effort

Home Page:https://ktor.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Exception message is lost on copy

ark-1 opened this issue · comments

Hi! I encountered an issue where the exception message was lost. What happened:

  • I catch ExceptionA with message "a"
  • I throw ExceptionB with this exception as cause and message "b"
  • In different step (?) ExceptionB with message "a" is caught. Message "b" is lost

I tracked it down to tryCopyException function in ExceptionConstructor.kt. It seems it only respects the cause, not the message.

internal fun <E : Throwable> tryCopyException(exception: E, cause: Throwable): E? {

This is not really a bug, we cannot do much here. The problem is that we cannot potentially know whether message is mutated or not.

Take a look at the following toy exception:

HttpCodeException(val cause: Throwable, val message: String) : Exception(cause, 
"HTTP request has failed with the following reason: $message. Please consider using KtorHttpResponseHandler to gracefully handle these error codes.")

Do you really want here to pass message of the original exception to the copied one? Probably not.

Potentially, we could try to guess whether an exception message is mutated or not by introspecting constructor parameter name, but this capability is available only in Java 8 (-> not compatible with our current Android-driven target).

So whatever choice we made, there would be a code that doesn't fit this choice.
I'd recommend implementing CopyableThrowable in your custom exception

The irony here is that your exception contains custom logic and mine does not (class ExceptionB(message: String, cause: Throwable) : Exception(message, cause)), and yet it is my exception that has to implement CopyableThrowable

The real irony is that we've tried the approach with invoking a constructor with String parameter unconditionally and received a lot of negative feedback because it made some 3rd-party exceptions (can't implement CopyableThrowable there) much harder to debug due to cumbersome messages, and yet we are here exchanging quips.

Unfortunately, decisions like this are always about trade-offs.