question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Make `AssertionError` extend `Exception`

See original GitHub issue

Currently, AssertionError extends java.lang.Error, which is wrong. It should instead extend ceylon.language.Exception.

The Java conventions are:

  1. Never throw a java.lang.Error unless the system is totally hosed
  2. Never catch an Error without re-throwing an Error or ending the process. The very rare exception to this rule is when the potential for a specific Error is expected

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.

It’s true that (2) is sometimes violated, for instance, by recovery code in servlet containers, but those few violations are irrelevant to this issue.

These conventions are good and correct, because in the face of an Error, the integrity of the process is in doubt. Carefully reviewed code that must run correctly, such as the following, may fail with an Error, which is totally unexpected:

try {
    // do stuff
}
finally {
    // the following may fail to complete due to an Error such as
    // StackOverflowError or OutOfMemoryError.
    clearAuthenticationTokenInThreadLocal(); // simple code that "can't" fail
}

A caller should not attempting to recover from an Error thrown by the above code, for example:

shared void run() {
    while (true) {
        try {
            serveRequest();
        }
        catch (Throwable t) {
            log(t);
            // It’s totally wrong to continue here!
        }
    }
}

However, this recovery code is perfectly fine:

while (true) {
    try {
        serveRequest();
    }
    catch (Exception e) {
        log(e); // probably bad user input or something
        reportErrorToUser(e);
    }
    catch (Error e) {
        try {
            log(e);
            reportErrorToUser(e);
        }
        finally {
            throw e; // system is totally hosed, be sure to re-throw
        }
    }
}

This recover code would also be fine without catch (Error e) { ... }.

In Ceylon 1.3.3, Errors in the form of AssertionError are thrown for perfectly ordinary things, such as failed parses, bad input, and common programming bugs such as equivalents to Java’s NullPointerException, ClassCastException, and IndexOutOfBoundsException (these should never happen in finally blocks).

For Java code calling Ceylon code, this causes a significant problem. Java code may, and often does, catch (Exception e), which misses Ceylon AssertionErrors which should be caught and handled.

For general/top-level Ceylon recovery code, having AssertionError extend Error requires the rather awkward catch (Exception | AssertionError e), rather than the simple catch (Exception e).

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:52 (51 by maintainers)

github_iconTop GitHub Comments

1reaction
jvasileffcommented, Aug 30, 2017

in precisely what way are they different

Because if an AssertionError (or any other Exception) happens in a very important finally block, “it’s your own damned fault.” But an Error is impossible to protect against, and therefore the presence of one indicates that the application state may be compromised, at least without the caller having very special knowledge of the code that was called (e.g. SOE in the type checker)

But I’ve already said that in different ways here, and in prior conversions.

From what I’ve seen of the SDK and IDE codebases, we indeed don’t commonly catch AssertionError (there is some infrastructure code where we handle them in the IDE, but that’s at the level of like concurrency management code, and indeed it’s in contexts where the IDE actually catches all Throwables, including Errors.)

The SDK isn’t an application, so that makes sense. In the IDE, it is at least suspect that Throwables are caught, rather than Exception | AssertionErrors. But I haven’t looked at the specific code you are taking about.

But you seemed to be dead against it

Yes, I am.

I mean is catch (Error~AssertionError) something anyone has ever needed to do? I doubt it.

You’d want catch (Exception | AssertionError), for sane course-grained, top-level recovery.

but I’m going to bow out now

Ok, really, that’s the last from me. I’ve made all of my arguments, so I’m going to unsubscribe from this thread.

0reactions
CPColincommented, Sep 5, 2017

You’re lucky, then!

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Overwrite AssertionError in Python and Use Custom ...
In this article, I will show you how simple it can be to make the assert statement raise a different exception instead of...
Read more >
assert - Customize AssertionError in Python - Stack Overflow
The issue is that you're not doing anything with self.message = msg + "+ SOME TEXT" . You have to pass the custom...
Read more >
Java Exception Handling - AssertionError - Airbrake Blog
A deep dive into the Java AssertionError, including fully functional code showing how to use assertions within Java and how to avoid it....
Read more >
Exception Handling & Assertion in Java
But you can always create you own Exception classes by extending from the class Exception or one of its subclasses. Note that RuntimeException...
Read more >
Built-in Exceptions — Python 3.11.1 documentation
User code can create subclasses that inherit from an exception type. It's recommended to only subclass one exception type at a time to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found