In future, could Kotlin have checked exception?

I would say that Exceptions (checked is even worse) are actually problematic in all cases where you wish to recover from the exception. It is possible to do this correctly, but 99% of the code is not actually exception safe. What that means is that if an exception is thrown somewhere in the wrong place the state of objects/the program may actually easily become inconsistent/invalid.

Checked exceptions add the issue with exception nesting. This is when you have to wrap an exception into another one just to meet requirements of an API that does not allow throwing that exception (and the API is not under your control). I can’t count the amount of times I have written something like:

  try {
     // do something throwing a NastyCheckedException
  } catch (e: NastyCheckedException) {
    throw RuntimeException(e)

Consensus seems that a Try monad (it sound scarier than it is) is the best (safest, clear, concise code). Despite having “monad” in the name.

1 Like

Just curious, has anyone submitted a formal request (for inspection option) by creating a ticket? Since my comment here over 2 years ago where I requested to have some sort of manual inspection option, I have continued to be bitten several times by the Android platform that throws exceptions left and right. The way you used to know about them, since it is very difficult to know all the exceptions thrown by Android framework, is that your Java code didn’t compile until your code addressed exceptions. Now, since Kotlin doesn’t check, I have had multiple production incidents.

I see there has been much continuous discussion in this post. I really couldn’t care for Kotlin to have checked exceptions, but I definitely still hope that the difficulty in developing Android apps gets addressed.


I agree some type of inspection that allows you to find any place throwing exceptions would be very very helpful.
Checked exceptions are a bad idea, but not knowing about reasonably likely exceptions is even worse. Seeing that many libraries are badly documented, not showing all @throws annotations or talking about it in the javadoc, this can be a real problem.

a Try monad is a clean solution (-> see Rust, Haskell, Elm, Purescript, and in some way even go, altough the double-return and if err != nil is not really a try-monad), but I fear that It would be nearly impossible to introduce the use of one as an exception-replacement by now.

What I could imagine happening is

  • allowing Result<T> to be used as a return type, and automatically returning error-values on Throw-statements in these functions, and returning the wrapped value automatically on normal returns, such as to make it possible to use Result<T> as a clean exception-replacement in self-written code. (Something like this is even mentioned in the KEEP for Result<T> so it’s not out of the question)
  • adding another Try monad-like and giving you the option to replace all checked exceptions that could be thrown by stdlib and java code with returning a wrapped try value via some compiler-option (This is unlikely to happen and i doubt that I’d actually like this)

TLDR: please use scrict typing.

to have some sort of manual inspection option

I can advice using sealed classes to create extended version of try monad.

I use this in my code. Just as an example, for network request operation you can draw something like this:

sealed class Response<TResult> {
     data class Success <TResult>(val data: TResult): Response<TResult>()

     sealed class Error<TResult>: Response<TResult>() {
            data class Deserialization<TResult>(val message: String, val first1000CharsFromRequest: String): Error<TResult>()

            data class ServerResponse<TResult>(val message: String, val code: Int): Error<TResult>()

            data class NetworkError<TResult>(val exception: IOException): Error<TResult>()

Next you can observe all possible scenarios in your code. This paradigm is used in Rust as primary (for example).

Moreover, please don’t rely on Throwable response from api, because it is just recommendation. It means, that if you compile your code with version1 of library, then version2 of the same library can have different response (e.g. in runtime you can work with a bit different api). It means, that your code can get unexpected exception on next Android versions.

Finally: I really advice you to take a look on sealed-based results. You are able to create really type-safe code and cover the most of scenarios in compile time, not exception-only, but success too.

This is the obvious solution for your own code, but that code is not the main problem (You hopefully know which exceptions you’re throwing, and if not, are hopefully already using sealed-class based result types.)

The big Problem is JVM-code that is out of your control. Android libraries are notoriously using Exceptions to notify you about anything even slightly unnormal, and many JVM-libaries rely on (checked) exceptions for their error paths too. If they are badly documented (which they shouldn’t be, but many still are, and we won’t be able to change that) you have no idea what could be thrown before trying out every possibility.

Even Kotlin libaries abuse exceptions in this way.
I still don’t know if I’m missing some exceptions that ktor's webclient can throw for some situations. I absolutely HATE that I have to do

try {
  val response =client.request<HttpResponse>(url)
  if (response.isOk()) {
} catch(e: Whatever) {
  // handle error 1
} catch(e: Whatever2 {
  // handle  error 2

instead of just having

val response = client.request<HttpResponse>(url)
when {
  response is ValidResponse && response.isOk() -> handleValidResponse(response)
  else -> handleInvalidResponse(response)

this is especially anoyying since for my main usecase i actually fully expect there to be many errors that would be represented as exceptions (Unknown Host stuff), and I want to handle these as data too. Having exceptions is anoyying. And yes, i DO define my own wrapper type and function.
But that is a lot of work if needed in many places (-> see android), and it makes the code harder to get in to as someone new needs to first understand all your custom error-representation logic

Actually I don’t know, what exception (and with what text, inner exceptions, etc.) will be thrown. And sometimes I need to parse exception text to determine real case (and, unfortunately, I have to write tests to verify this).

So in real life code can throw CancellationException, because of timeout or because of client close. And I have to determine this (please note, that type is exact the same).

Therefore I have DMZ-like layer to split scenarios to useful for me. For example, code above doesn’t know to differ TCP-like errors and TLS-like ones. All of them are “network-related”. And because of all these facts I advice writing intermediate code between library and your system. So you will be on the safe side in your code, and you will able to cover everything useful in this layer.

We do need some tool in the language which handles recoverable failures. This doesn’t have to be checked exceptions in particular and it doesn’t need to force developers to handle exceptions, but it needs to do the following:

  1. Warn the developer about potential recoverable conditions arising from a function call;
  2. Allow to unwind the stack automatically if the developer opts to not handle them at the call site.

Currently Kotlin has taken away the tool we had and given us nothing to replace it. The only option mentioned was sealed classes, but they are a poor replacement since they can’t help you if you call Java code which relies on exceptions, they are cumbersome to write for each function which can fail, and they don’t have automatic stack unwinding. Documenting thrown exceptions is something that compiler doesn’t help with in any way, it’s easy to omit something, and the documentation often becomes obsolete very quickly.

Checked exceptions don’t mix well with functional code, but Kotlin doesn’t have functional exception handling either. Rust has ? to unwind the stack when encountering Err, and it can transform one type of exceptions into another. Haskell has the do notation. Kotlin has neither, and even if it had, it also had to have some way to map Java calls into that solution, otherwise interoperation becomes difficult to achieve.

large stable systems with several tiers and multiple modules have been built in languages which do not include any form of checked exceptions

And they have also been written in languages without null-safety, does that mean we don’t need it? This fact proves nothing.

The correct point to handle exceptions is a central exception handler that normalizes how to treat them.

No, the correct way to handle exceptions is to handle them at an appropriate layer. If it is in the wrong layer, the error handling code doesn’t have the context it needs to react appropriately. Reacting to exceptions at a level too high is just as difficult as if it is too low.

This is a quote from Eckel if I’m not mistaken, who quoted some C# developer on why C# doesn’t include checked exceptions. The original source is long gone. Which projects were investigated, what the methodology was, and what exact numbers they had we’ll probably never know. We need to rely on verifiable facts which reflect the current experience, not something someone said some time ago in unknown circumstances.


The only thing that Kotlin does is not check that you handled all exceptions that could potentially occur. It supports exceptions, even the ones that are checked for the Java language. It merely treats all exceptions as unchecked. The biggest interop issue with Java is if you throw an exception from Kotlin that Java code would not have been able to throw, and this exception is then not handled properly by the original caller.

Yes, and that takes away the ability to reliably handle recoverable failures while not giving an alternative.

1 Like

I really like this summary of the situation.
Kotlin, the language that had the goal of bringing null-safety and better compiler guarantees to the JVM (see sealed classes, null-safety, even coroutines to some extent), took away a core part of how Java deals with failures: Forcing you to recover from them, or at least handle them. This would be okay if Kotlin somehow replaced it. But it doesn’t.

Checked exceptions are bad, but they are also better than nothing. Not even having compiler generated Throws annotations is… well it’s stupid. The compiler should at least TELL us when we can expect an exception to be thrown. And it should allow us to handle them in a good way.

I love the approach of introducing something like do-notation and then adding a Result-type that functions more like Rust or Haskells types do than the current “pretty much just try-catch, but as a stdlib-function, not a language-feature”. Introduce such a type, add Do-notation (maybe together with KEEP-87, make this a “typeclass”, so we all can use it). Then generate Throw-annotations by the compiler and warn against non-handled exceptions. keep the current runCatching-concept, but let people specify the type(s) of the exceptions that should be caught. This would work well with the proposed Union types (for multiple exceptions).

THEN, and only THEN will kotlin have usable error handling. as it is right now, this is by far the worst weak spot of kotlin, and it’s the only place i could see people saying “I will keep using java” and actually have a POINT.


Eckel quoted it but did not originate it and is not the only one. Here is a link to another source, which is also quoted in Wikipedia, but also references it through J.R. Kiniry. Without a clear source, I simply said it was “oft quoted”

I know he didn’t, that’s exactly what I said in the first sentence further down, I only didn’t find the page behind the link he used. Having read that, it strengthens my argument even more: apparently there never was a proper scientific research, just some internal investigations at Microsoft conducted in 2000 or before that when Java was far from mature.

Basically the only argument in that post relevant to the current discussion is that checked exceptions increase robustness at the expense of productivity when writing code and can be abused. Both points hardly apply to Kotlin since the language does favor robustness like null-safety and is not afraid of giving the programmers tools which can be abused like operator overloading. And if Kotlin emphasizes robustness, it would only make sense to do what increases it and not follow other languages.

Also that post assumes that support of both checked and unchecked exceptions in Java is a flaw, whereas it is a crucial feature as some errors are programmer’s errors, and some are expected and recoverable. It’s definitely not impossible to distinguish between these two cases as the post author claims.

I was primarily responding to the insinuation that I should have attributed it to Eckel.

But since you seem to demand response to the wider argument, I can say that as a Java programmer, that I whole heartedly agree with the quote.

The problem with them is not just lost productivity. You could have made that case in the early days of Java when everything was imperative coding. But when you enter the world of functional programming, where you have higher level functions like map, filter, forEach, etc. that take other functions, checked exceptions are major issue.

We have generics that allow you to parameterize the return value, but nothing like that for parameterizing exceptions. Forcing callers to deal with errors instead of totally ignoring them is a good thing, but the mechanism of checked exceptions is not a good way to do it. The real problem isn’t with forcing callers to deal with exceptions its the way that Java’s checked exceptions do that.

What after all are checked exceptions? In reality they are alternative return values for the function but they do so in a way that is like a GOTO. The best way to force handling of errors is making them part of the return value using something like Kotlin’s Result type or one of the many alternatives see Arrow’s types and some more explanation on the problem with exceptions

How’s that an insinuation? I only said that Eckel quoted some C# developer and that’s how this quote became popular. It doesn’t really matter who said it, what matters is that there is no proper scientific research behind the claim.

As to the rest of the post, I said right in my first comment that we don’t need to have checked exceptions in particular, so I’m not claiming in any way that checked exceptions are perfect. But right now Kotlin has nothing at all. I’ve already explained why sealed classes don’t help. Libraries like Arrow won’t help for the same reason.

Declaring an exception that is known to be recoverable is equivalent to declaring a more complex return type like a discriminated union of success and error values. This of course satisfies your requirement #1.

I think you stuck in requirement #2 to disallow to specifically disallow that, but it’s just syntactic sugar for returning the error out to the caller. I expect that if you were to argue that it’s more fundamental,
then you would be relying on a pattern of functions having secret knowledge about their callers, which is a horrible idea and doesn’t even support the premise.

So… Kotlin supports these kinds of return types, of course. Occasionally they are useful, and when they are you can just make a complex return type.

Granted, Java with its checked exceptions supports these kinds of discriminated return value pretty well, except that they can’t be folded into generic return types. That’s pretty annoying.

The big problem with checked exceptions in Java, though, is that they are used for other things, and it has caused a lot of problems. All the methods of OutputStream, for example, throw IOException. Is that recoverable? How could the author of that interface possibly know. It doesn’t even specify an error condition. It means only that it is an error that prevented the IO operation from succeeding. The OutputStream interface is independent of the target of the data, and doesn’t even know if there are any possible “recoverable” errors at all, yet it still declares the exception, and now you can’t connect a source to a ByteArrayOutputStream without somebody writing code that will never be called to handle these impossible “recoverable” errors.

It turns out that the vast majority of interface methods that declare a checked exception are written without any specific knowledge of the real errors that might occur, because they are in abstract interfaces like OutputStream. The abstract interface has no notion of which error conditions may actually occur, and which of them are recoverable. They might as well all just declare ‘Exception’, but it’s even easier if we just assume that everything does… like Kotlin.

The responsibility for handling recoverable errors should usually reside with the composition root, which decides which actual implementation will be used for the abstract interface. If I pass a FileOutputStream to a method that takes an OutputStream, then I have to know that it could run into space restrictions, and it’s my job to take care of that.

There’s no reason to mess up all the intermediary code, since checked exceptions don’t add any value at all in this situation.

1 Like

I might add something more about how I use checked exceptions in Java. This might give you, the reader, an appreciation for why they have use, even if perhaps, this use may have a narrow scope.

My code creates instances of a thread sub-type I call a thinker. These thinkers have the following in their run method:

public final void run(){
    }catch(PonderableDilemma x){

The abstract think method throws a ponderable dilemma, and the ponder method of this dilemma is also abstract; its implementation can take some corrective action that makes sense in terms of the ponderable dilemma that is thrown.

Another type of checked exception called an imponderable dilemma is thrown in almost all other methods of my code. Imponderable dilemmas are not ponderable ones; they cannot be caught in the run method of my thinkers and they do not declare a ponder method. This means that the developer must implement a ponderable dilemma that responds appropriately to any imponderable dilemma which makes sense to the context under which a given thinker is operating. At least as important is that the developer does not have to consider run-time context in methods which throw imponderable dilemmas.

I find this mechanism to be very useful; it forces the developer to determine whether there is a context under which a problem occurs, and gives the developer an opportunity to craft an algorithm that permits the system to take corrective action. For instance, the ponderable dilemma may spawn one or more other thinkers whose job is to take a particular corrective action.

Almost all features of Kotlin are syntactic sugar over Java, except for a few ones. If we are dismissing features on the basis that they are syntactic sugar, I might as well just write stuff in Java. Would you argue that data classes are not useful since they are just syntactic sugar for manually written methods? I don’t think so. Then why are you trying to argue that syntactic sugar is not important for stack unwinding? If there is no syntactic sugar for this, the code becomes really verbose. This is an important requirement.

Another problem with sealed classes I menioned, but you didn’t address, is that it doesn’t help when you work with Java code. Sealed classes don’t help with functions which don’t return a success value, but can potentialy fail, either.

Of course, he can. Do you really want to crash the program if the network failed or if the disk was busy? Effective Java has an item on this, by the way, which answers the question better.

And that’s why my first point reads “warn the developer” and not “force the developer”.

So you’ve fed an object capable of throwing I/O exceptions into a library. You have to handle it. How do you tell which methods of the library will now potentially throw these exceptions? And how do you make sure you didn’t forget to handle any?

1 Like

Maybe I’m not following some of the above, but I have a suggestion that seems to address some of these issues:

Kotlin should infer which exceptions a method or lambda could throw, without requiring an explicit @Throws declaration.

Java’s checked exception handling has two parts: if you’re doing something that could throw an exception, you either have to catch the exception, or declare it.

Of those two, catching an exception is a local matter; it’s all dealt with within the method, and no-one else needs to know. So removing that requirement doesn’t itself have wider effects. (It might help if an IDE warned about uncaught exceptions, for people who want to know about them.)

But declaring them is where you get the bigger interactions. And it’s a pain, because in almost all cases it’s boilerplate; the compiler already knows which exceptions you haven’t caught, and so could generate that declaration for you. (Kotlin added lots of type inference already; in some ways, it’s strange they didn’t add this too.)

This inference would improve interoperability with Java code: when calling Kotlin methods, it would always know which exceptions could arise, and so Java’s strong exception checking would still apply; and the declaration would still ‘bubble up’ to the point it’s caught, whichever combination of languages were used.

It wouldn’t make exceptions ‘checked’ in Kotlin; Kotlin code would still be free to ignore them. But the information about them would no longer be lost; at any point in the code you’d always know which exceptions could be thrown, so you could make more informed decisions about what to handle.

The problem case is around lambdas; that’s where things get painful in Java. But in Kotlin, most lambdas get inlined, so this shouldn’t be a problem! (I’m not sure what should happen where they’re not inlined; perhaps the compiler can do something akin to type parameterisation? Or maybe that would have to be a corner case it doesn’t handle.)

To me, this sounds the best of both worlds, giving developers all the information they’d get from checked exceptions, without requiring any extra code.


Of course not. I want to catch the exceptions that I know how to handle. It doesn’t matter whether or not they are subclasses of IOException. Checked exceptions don’t make the situation better.

Well, because “recovering” from an exception involves not just knowing which exception was thrown, but what operation was interrupted, and I know what the object I passed in was for, I know to expect the exception in the cases where I can recover from it. It’s not automatic, but… When you’ve fed an object capable of throwing IO exceptions to a library, how do you know which methods of the library will potentially throw these exceptions? It’s the same answer, really, but usually more complicated, because now you have to anticipate that they’ll be wrapped as the cause of other more general exception types. Checked exceptions don’t make the situation better.

1 Like

You know, I’d never “force the developer” into a retaliation by obliquely misquoting something they said earlier and throwing it back in their face in a stupefyingly pithy aphorism which tries to underscore some subjective, useless, and thereby idiotic, point about etiquette.

There’s a few more bits for the reader to chew on. I’m done.