Intermediate 25 min read

Try, Catch, and Finally

By the end of this lesson, you'll be able to:

  • Write a try/catch block to handle a runtime exception without crashing
  • Explain what code inside finally guarantees
  • Recognize the difference between an exception being thrown and being handled

Prerequisites: "ApexDoc and Documentation Standards"

Catching an exception

Decimal result;

try {
    result = 10 / 0;
} catch (MathException e) {
    System.debug('Caught a math error: ' + e.getMessage());
    result = 0;
}

System.debug('Continuing normally: ' + result);
  1. Decimal result; — declared outside the try so it's still visible afterward.
  2. (blank line)
  3. try { — try marks the block that might fail.
  4. result = 10 / 0; — without try/catch, this alone would throw a MathException and immediately stop the whole transaction (as seen back in Module 8).
  5. } catch (MathException e) { — catch steps in specifically for a MathException.
  6. System.debug('Caught a math error: ' + e.getMessage()); — handles the problem instead of crashing.
  7. result = 0; — recovers with a sensible fallback value.
  8. } — closes the catch.
  9. (blank line)
  10. System.debug('Continuing normally: ' + result); — this line still runs — execution continues normally after the caught error.

finally always runs

try {
    Decimal result = 10 / 0;
} catch (MathException e) {
    System.debug('Handled: ' + e.getMessage());
} finally {
    System.debug('This always runs, error or not.');
}
  1. try { — the risky block.
  2. Decimal result = 10 / 0; — throws a MathException.
  3. } catch (MathException e) { — catches it.
  4. System.debug('Handled: ' + e.getMessage()); — handles it.
  5. } finally { — finally runs whether the try succeeded, failed and got caught, or even failed in a way nothing caught.
  6. System.debug('This always runs, error or not.'); — the right place for cleanup that must always happen regardless of outcome.
  7. } — closes the finally.

A real business example: Order Processing

public String processOrder(Decimal orderTotal, Decimal discountPercent) {
    try {
        Decimal discount = orderTotal * (discountPercent / 100);
        return 'Order total after discount: ' + (orderTotal - discount);
    } catch (Exception e) {
        System.debug('Failed to process order: ' + e.getMessage());
        return 'Order could not be processed.';
    } finally {
        System.debug('Order processing attempt finished at ' + System.now());
    }
}
  1. public String processOrder(Decimal orderTotal, Decimal discountPercent) { — the method.
  2. try { — wraps the risky calculation.
  3. Decimal discount = orderTotal * (discountPercent / 100); — the calculation that might fail for any number of reasons.
  4. return 'Order total after discount: ' + (orderTotal - discount); — the success path.
  5. } catch (Exception e) { — a generic catch-all for whatever goes wrong.
  6. System.debug('Failed to process order: ' + e.getMessage()); — logs the failure.
  7. return 'Order could not be processed.'; — returns a sensible fallback message instead of crashing.
  8. } finally { — runs no matter which path above was taken.
  9. System.debug('Order processing attempt finished at ' + System.now()); — logs that the attempt happened, successful or not, useful for auditing.
  10. } — closes the finally.
  11. } — closes the method.

Exercise

Write a try/catch that attempts Decimal result = 20 / 0, catches MathException, debugs "Division failed", and uses finally to debug "Attempt complete".

Show hint

try { ... } catch (MathException e) { ... } finally { ... }

Salesforce: ○ Not connected Connect
APEX

Execution Results

Run your code to see the result.

Try, Catch, and Finally Quiz

1. When does code inside a finally block run?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

try/catch lets code recover from a runtime error instead of crashing the whole transaction; finally guarantees a block of cleanup code runs no matter what happened in the try.