guava icon indicating copy to clipboard operation
guava copied to clipboard

Error being undetected by the SubscriberExceptionHandler

Open Jiabao-Sun opened this issue 11 months ago • 3 comments

API(s)

`com.google.common.eventbus.Subscriber#dispatchEvent`

How do you want it to be improved?

  final void dispatchEvent(final Object event) {
    executor.execute(
        new Runnable() {
          @Override
          public void run() {
            try {
              invokeSubscriberMethod(event);
            } catch (InvocationTargetException e) {
              bus.handleSubscriberException(e.getCause(), context(event));
            } catch(Throwable e) {
              bus.handleSubscriberException(e, context(event));
            }
          }
        });
  }

Why do we need it to be improved?

The Subscriber#dispatchEvent did not catch Throwable, resulting in the Error being undetected by the SubscriberExceptionHandler

Example

-

Current Behavior

Desired Behavior

Error can be detected by the SubscriberExceptionHandler

Concrete Use Cases

Checklist

Jiabao-Sun avatar Mar 19 '25 13:03 Jiabao-Sun

First, a disclaimer: we recommend against using this API.

Can you say a bit about what kind of Error you are seeing here? It's not one that is thrown by the @Subscribe method, since that would be wrapped in an InvocationTargetException and handled by the existing code. So presumably something like OutOfMemoryError or LinkageError. It's not obvious to me that catching and logging such an Error is the right thing to do.

eamonnmcmanus avatar Mar 19 '25 13:03 eamonnmcmanus

Thanks @eamonnmcmanus for the quick feedback. When encountering ERRORs such as StackOverflowError, losing the problem stack trace can make troubleshooting extremely difficult.

Jiabao-Sun avatar Mar 20 '25 03:03 Jiabao-Sun

Updating dispatchEvent to catch Throwable instead of only InvocationTargetException makes the system more robust, production-safe, and easier to debug. This change aligns with fail-safe principles in asynchronous and event-driven architectures.

final void dispatchEvent(final Object event) {
    executor.execute(
        new Runnable() {
            @Override
            public void run() {
                try {
                    invokeSubscriberMethod(event);
                } catch (InvocationTargetException e) {
                    bus.handleSubscriberException(e.getCause(), context(event));
                } catch (Throwable e) { // added to catch Errors and other Throwables
                    bus.handleSubscriberException(e, context(event));
                }
            }
        });
}

Ayushkhodankar avatar Jun 01 '25 15:06 Ayushkhodankar