Rocket ship badge DevOps Launchpad

Rob Cowell · 31st January 2024

Crafting more resilient Salesforce apps with advanced Apex error handling

Ever find yourself grappling with unexpected errors in your Apex code? Well you’re in good company, so let’s tackle this head-on. We’re diving into advanced Apex error-handling techniques that promise to transform your Salesforce apps from just working to wonderfully resilient. Ready to level up your error-handling game? Let’s jump in!

Exception-handling best practices

Before we jump into the nuts and bolts of Apex’s exception hierarchy, let’s lay the groundwork with some essential exception-handling best practices. These practices are like the golden rules, the guiding stars that will help us navigate the often choppy waters of software development.

  • Always be specific: When catching exceptions, specificity is key. It’s tempting to catch a broad exception class, but being specific helps you handle each error type more effectively.
  • Avoid swallowing exceptions: An easy trap to fall into is silently catching an exception without any action. Always ensure that each caught exception is either logged or handled appropriately to avoid ghost errors that leave no trace.
  • Keep user experience in mind: When designing error messages, remember the end user. Errors should provide clear, non-technical feedback that helps users understand what went wrong and, if possible, how to fix it.
  • Prioritize system stability: Your error handling should always aim to maintain the stability of your system. This means considering rollback mechanisms or alternative workflows in case of failures.
  • Embrace logging: Good logging is invaluable. It helps in diagnosing issues and understanding the application’s behavior over time. Use logging judiciously to record key information about exceptions and errors.
  • Plan for recovery: Design your error handling with recovery strategies in mind. Think about how the application can gracefully recover from an unexpected state.

Understanding the Apex exception hierarchy

First things first: understanding the Apex exception hierarchy on the Salesforce platform. This is Salesforce’s way of categorizing exceptions in Apex, and it’s a bit like a family tree for errors. At the very top, we have the Exception class — think of it as the head of the family. From there, it branches out into more specific exception types like DmlException, QueryException, LimitException, and so on. Each of these exceptions sheds more light on what exactly went wrong in your code.

So, why should we care about this hierarchy? It’s simple. Knowing the type of exception is like having a roadmap to the issue. It tells us not just that something went wrong, but gives us clues about where and why. For instance, handling a LimitException is a different ballgame compared to handling a DmlException. The former deals with governor limits in Salesforce — those pesky rules that keep our applications in check — while the latter is about DML operations.

When it comes to using this hierarchy, there’s a golden rule: catch only what you can handle. It might be tempting to just catch the generic Exception class and call it a day, but that’s like putting a band-aid on a broken arm. Instead, aim for precision. Catch specific exceptions wherever possible. This targeted approach lets you write error handling code that’s tailor-made for the problem at hand. Doing a DML operation? Be on the lookout for a DmlException.

But what about those times when the standard exceptions just don’t fit the bill? That’s where you can get creative and extend the exception hierarchy to suit your needs. If you encounter a unique error scenario that Salesforce’s standard exceptions don’t cover, go ahead and craft your own custom exception. This gives you more control and clarity over your error-handling strategy.

Navigating the Apex exception hierarchy effectively is all about balance. It’s like being a tightrope walker, maintaining just the right equilibrium between catching specific, actionable exceptions and creating your own for unique scenarios. This approach not only sharpens your error-handling skills but also boosts the maintainability and readability of your code.

Remember, every exception type is telling you a story about what went awry. Your job as a savvy Salesforce developer is to listen to these stories, understand them, and then take meaningful action. By getting a grip on the Apex exception hierarchy, you ensure that your Salesforce applications aren’t just handling errors — they’re doing it in a way that’s meaningful, precise, and, ultimately, incredibly effective.

Using custom exceptions

Custom exceptions in Apex are like having a tailor-made suit. They fit your application’s needs perfectly. These exceptions allow you to define and handle very specific error scenarios, adding clarity and predictability to your application.

Picture yourself as a detective on the trail of solving a mystery, but the only clues you have are vague and generic. Frustrating, right? That’s the experience when dealing with generic exceptions in your code. They raise their hands saying, “Hey, something’s wrong here,” but they’re not helpful enough to tell you why or how to fix it. This is where custom exceptions become the heroes of our story. They’re those detailed, specific clues that lead you straight to the heart of the problem.

When you create custom exceptions in Apex, you’re empowered to define your own, very specific error conditions. They let you capture the exact scenarios that could go awry in your application. Let’s say you’re processing a mountain of data. A generic exception might unhelpfully shrug and say, “Oops, something broke,” but a custom exception can pinpoint precisely which record tripped the alarm and why.

Creating a custom exception in Apex is surprisingly straightforward. It’s as simple as adding your own Apex classes that extend the built-in exception class, then adding your own structure and logic. It’s like crafting a bespoke tool tailored to your application’s needs.

But the magic isn’t just in creating these exceptions; it’s in how you use them. Throwing a custom exception in your code is like sending a clear, concise message about what went wrong. It’s a beacon that guides you during debugging. More so, it makes your code self-documenting. Other developers can read your code and understand the “whys” and “hows” of your error handling with ease.

For instance, imagine you have a method for processing payments. If something goes awry with the payment gateway, rather than tossing a generic exception into the mix, you throw a PaymentGatewayException as defined in your custom exception class. This can be caught in a catch block specifically for that exception type and instantly informs the developer or support team about the exact location of the problem, making it much easier to debug any issues.

So, here’s the key takeaway: handling errors is not just about putting out fires; it’s about doing so in a way that adds predictability and clarity to your application. Having a custom exception system is your first step toward achieving this level of control and understanding in your Salesforce applications.

Leveraging an error logging framework

Next up, let’s talk about error logging. Why build an entire logging system from scratch when you can stand on the shoulders of giants? Using a pre-built logging framework like Nebula Logger (or other great options out there) not only saves time but also brings the wisdom of the Salesforce community into your application. Think of your logging system as the detective of your app, always on the lookout and keeping detailed records of every mishap.

Why go for a pre-built framework like Nebula Logger? Two words: efficiency and community. Nebula Logger is an open-source tool developed and refined by the Salesforce community. It stands out for its centralized logging, which is essential for managing errors in extensive Salesforce implementations. This approach consolidates all error-related data in one place, providing a comprehensive view of your application’s health. This grouping extends to capturing instances of the same issue together, like DML statement related issues, so that you can gauge the extent of an issue — was it an isolated incident, or a more deep-rooted problem in your code execution?

Nebula Logger’s versatility shines through its ability to log a wide range of data, from simple messages to complex structures, and it’s not just limited to Apex — it works with Flows and Lightning Components, too. Its integration with Salesforce objects adds another layer of usefulness, linking logs to specific processes and records for enriched troubleshooting.

Setting up dynamic error notifications

With a solid logging system like Nebula Logger in place, the next step in our error-handling journey is dynamic error notification. This is where we make sure the right people get alerted as soon as an error pops up.

Think of dynamic error notifications as the smoke detector of your Salesforce application. They’re there to give your administrators or developers a heads-up on issues, paving the way for swift action. Salesforce offers a range of tools for this, including email services, platform events, and custom Apex methods. The idea is to set off these notifications based on specific conditions or the severity of the error logged.

Let’s say you have a critical error affecting your app’s performance. You could set up an email alert for this. For less urgent issues, a platform event might suffice, keeping relevant team members in the loop without causing alarm. The trick is in the details: tailoring the content of these notifications to be as informative as possible, so your team has everything they need to jump into action.

But there’s a fine line to walk here. Bombard your team with every tiny error, and they’ll get overwhelmed. Be too sparse with the details, and significant issues might slip through the cracks. The goal is to find that sweet spot where your team stays informed but not inundated.

Governance and recovery protocols

Governance and recovery protocols are the unsung heroes of error handling. Your Salesforce applications should gracefully handle and recover from errors, keeping disruptions for end users to a minimum and safeguarding data integrity.

Governance in error handling is like setting the ground rules. It involves defining what makes an error recoverable or not, deciding when to retry operations, and establishing how to record error statuses. These policies and best practices are the backbone of effective error management.

A key component here is retry logic. Think of it as your app’s resilience mechanism. If a temporary glitch causes a failure, a smart retry logic allows the app to reattempt processing, often resolving the issue without needing any manual intervention.

Then there’s the concept of handling partial successes, especially in batch processing. Salesforce batch jobs handle loads of data, and it’s crucial that a single error doesn't bring the whole process to a standstill. That’s where transaction control steps in. It ensures that while errors are dealt with, successful operations aren’t undone.

Recording the status of each transaction or process is another critical aspect. This isn’t just about keeping a scorecard; it’s invaluable for analyzing what went wrong and how to improve things in the future.

Imagine a batch Apex job. If it encounters an error, it doesn’t just give up. Instead, it logs the error, keeps going with the next set of records, and triggers a recovery protocol for the failed records, like queuing them for another try. This means the batch is executed for as many records as possible, which makes your processes more efficient.

These protocols aren’t just technical maneuvers; they’re about proactive planning and scenario management. It’s about asking the right questions — how to minimize data loss, ensure continuity, and what the system should do in the face of an error.

In essence, governance and recovery protocols are your failsafe. They ensure that when — not if — things go sideways, your Salesforce application is well equipped not just to manage the error, but to recover from it with grace, keeping the impact on your users and business operations as minimal as possible.

Context-aware exception handling

Finally, let’s talk about being context-smart with your error handling. Why is context so vital here? Simply put, not all Apex code is created equal. The approach you take to handle an error in a batch Apex job can be worlds apart from how you’d manage it in a trigger or during a synchronous transaction. Adapting to these different environments is crucial for creating applications that are not just resilient but also user-friendly.

Let’s unpack this with some real-life examples. In the realm of batch Apex, where you’re juggling large volumes of data over extended periods, an effective error-handling strategy might be about logging errors without stopping the whole process. Implementing retry mechanisms for the bits that didn’t work the first time ensures that one hiccup doesn’t stall the entire operation.

Now, flip the script and think about a trigger or a user-driven transaction. Here, the game is all about immediate feedback. If something goes wrong, you want to provide clear, quick information to the user — what the issue is and how it might be fixed. This not only enhances the user experience, but also helps keep your data integrity in check.

So, how do we do this in Apex? It starts with understanding the context: is it a trigger, a batch job, a future method, or a synchronous transaction? With this insight, you can craft an error handling approach that fits like a glove. In batch processes, for instance, using Database.Stateful helps maintain state across transactions and manage errors smartly. In the world of triggers, the addError method is your friend for sending user-friendly error messages.

The core of context-aware exception handling lies in its flexibility and adaptability. It’s about asking the right questions: what’s the most suitable way to handle an error in this specific scenario? How can we minimize disruption and maximize value for the end user or the system?

By embracing context-aware exception handling in your Salesforce applications, you’re doing more than just reacting to errors — you’re proactively designing your system to address them in the most suitable way depending on the situation. This thoughtful, tailored approach to handling exceptions is what elevates a good Salesforce application to a great one.

Keep learning!

And there you have it: a roadmap to advanced Salesforce Apex error handling. By embracing these techniques, you’re not just fixing errors; you’re elevating the resilience and reliability of your Salesforce applications. So go ahead, experiment with these strategies in your orgs. Turn every error into a learning experience and a step towards creating more robust Salesforce apps. Happy trailblazing in the world of Salesforce development!

Find out more about testing your Salesforce implementations and automating that testing with this free course from DevOps Launchpad.

Join the virtual DevOps Summit!

Keen to keep learning? Gearset’s virtual DevOps Summit is just around the corner, on March 12th. Sign up now to discover the latest trends, as DevOps Advocate Jack McCurdy presents the results from the State of Salesforce DevOps 2024!