2

I have a small Salesforce app called ISV Cockpit that helps AppExchange partners to get notified about their app's unhandled exceptions within subscriber orgs.

For that, this app leverages Salesforce native error emails. So the app is not sending anything.

I am now considering extending the app's scope by reporting already handled exceptions with the same mechanism. The idea goes like this:

  1. The exception is first handled by the app's code:

    try {
        ....
    }
    catch(Exception ex) {
       handle(ex);
       silentlyRethrow(ex);
    }
    
  2. Then some library code converts the exception into a Platform event and publishes it

    private void silentlyRethrow(Exception ex) {
       Exception__e exceptionEvent = convertToEvent(ex);
       EventBus.publish(exceptionEvent);
    }
    
  3. Finally, a trigger unpacks and throws the exception:

    trigger ExceptionEvents on ExceptionEvent__e (after insert) {
      throw deserialize(Trigger.new);
    }
    

Can this work? I am currently struggling with serializing and deserializing exceptions but maybe this already indicates my idea is silly.

2
  • 2
    What specific use cases are you trying to help with? And why does it need to be in a separate transaction? For governor limit reasons?
    – Phil W
    Feb 14 at 19:14
  • Many ISVs handle most exceptions and there are no error emails. Many ask if my app could also tell them when exceptions occurred but were "handled". I thought I could rethrow them in a context invisible to the user but observed by the standard mechanism. With the benefit of getting the same nice error mails. Feb 15 at 9:05

1 Answer 1

2

You can't serialize or deserialize exceptions because they rely on transaction-specific memory graphs and stack; they are binary data under the hood. As an external developer, I can only peer from the outside, but even those glimpses are interesting.

For example, a divide by zero math exception will use 19 bytes of heap in execute anonymous, unless thrown from a method, in which case it will be 20 or 23 bytes of heap depending on if the method that threw the exception has parameters (+3 bytes if using parameters). And this is despite the fact that the stack trace itself will always be at least the size of the entire exception in heap size in an execute anonymous script.

Some other objects, like Database.SavePoint, exhibit a similar behavior. They can't be serialized because they're in some transaction-specific format that, even if you could serialize them, couldn't be deserialized in another transaction. Try serializing an sObjectType token (e.g. JSON.serialize(Account.class), or many of the other standard library objects.

Of course, you could still extract the strings and send them over the bus. You'd want to do this if you're in a scenario where you want to indicate an error to Lightning but still want the error to survive. On the other hand, since you're not really throwing the exception again, maybe you'd consider a future or queueable a better solution, as you're not firing off events that could even potentially be subscribed to by anyone in the org.

1
  • 1
    A future or queueable would likely be unhelpful as these cannot survive a governor limit issues in the same transaction, or a transaction that ends in an uncaught exception, and while this specific question is around caught exceptions these can still happen in a transaction that ultimately fails.
    – Phil W
    Feb 15 at 7:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .