Why NotImplementedError inherits Error?

In Java:

“An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.”
(https://docs.oracle.com/javase/8/docs/api/java/lang/Error.html)

So I for example am not used to catch Error. What I would do with likes of OutOfMemoryError or ThreadDeath?

But NotImplementedError want to catch and retrieve valuable info from it maybe.

Wouldn’t it be better for NotImplementedError to extend RuntimeException instead?

There are circumstances (such as logging, as you say) in which it could make sense to catch an Error. However, it’s generally not something you can recover from; the application is in an unknown state, probably can’t continue, and the best approach is often to let the application shut down; it can then restart (automatically or manually).

I had one app which occasionally had OutOfMemoryErrors (at least, until I fixed all the memory leaks…). The problem was that it was multithreaded; the error would crash a single thread (and free any object references held only by that thread), but the remaining threads would often continue merrily; depending which thread crashed, it might stop reading some input streams, or stop doing particular types of processing, or stop writing the results to a DB, or whatever – the effects could be quite subtle and easy for monitoring systems to miss. So the safest workaround was to catch all errors and shut down the whole app; it would then get restarted automatically, giving a short break in the data but avoiding any long-term effects.

There are some subtle difficulties in catching Errors. In particular, since the app may be out of memory, anything you do in an error handler that constructs any new objects (even just Strings) could fail with another OutOfMemoryError. So if you’re doing any logging or other processing, at the least you need to trap any errors thrown by that and ensure that you shut down the app no matter what happens.

Why would you want to catch NotImplementedError? Usually it is thrown by TODO() function to indicate that some execution path in your code is not yet implemented. Such situation is not supposed to recover from in run time. Instead one should replace that error throwing code path with the actual code.

This differs from the situation when the code is considered implemented, but intentionally not supporting a particular state or a combination of input parameters or an operation. In that case it would be more suitable to throw UnsupportedOperationException, which is inherited exactly from RuntimeException.

2 Likes

I don’t see why TODO() can’t throw UnsupportedOperationException. My point was that when my code (often injected by IDEA) throws “An Error […] that a reasonable application should not try to catch” it’s a bit unexpected and strange.

IMO TODO shouldnt be changed. For me TODO means that something is not implemented (yet) so it should be an NotImplementedError. As @ilya.gorbunov said, there is no way to recover from that since you are in an undefined state.
An UnsupportedOperationException should be thrown if you decide that something is not supported. But then it shouldn’t be makred with TODO().
I’d be fine with a function for that though:

fun UNSUPPORTED(): Nothing = throw UnsupportedOperationException()

That way TODO() keeps it’s meaning and you can easily replace the TODO()s generated by Idea with a quick find/replace.

1 Like

IMO TODO() no more severe than NPE and the recovery is the same as for the rest of RuntimeExceptions - just report it and carry on.

But thank you for your tip - I’m going with UNSUPPORTED()