# Exception handling and custom exceptions

*Platform Developer Study Guide · Process Automation and Logic · Last updated October 15, 2026 · https://www.certifyforce.com/study-guide/platform-developer/process-automation-and-logic/exception-handling-and-custom-exceptions*

How try, catch and finally run in Apex, which built-in exceptions to expect and which can't be caught, how to declare and throw a custom exception, and how DML errors, addError and partial-success DML decide what is rolled back.

- Certification: Salesforce Platform Developer
- Exam section: Process Automation and Logic
- Study guide: https://www.certifyforce.com/study-guide/platform-developer

**Official exam objective:**

> Implement exception handling in Apex, including custom exceptions as needed.

## What the exam expects

- Predict which lines run in a try-catch-finally block, including the order in which several catch blocks are tested.
- Name the built-in exception a scenario raises (DmlException, QueryException, NullPointerException, ListException, SObjectException) and know that LimitException can't be caught.
- Declare, throw and catch a custom exception, and wrap a lower-level exception as its cause.
- Handle DML failures: catch a DmlException, use partial-success Database methods, or call `addError()` in a trigger, and predict what is rolled back in each case.

Key terms: **exception** (an error that halts normal execution and bubbles up to the nearest matching catch); **catch block** (code that handles one exception type); **finally block** (cleanup code that always runs); **custom exception** (your own class that extends Exception); **addError()** (marks a trigger record as failed with a message).

## Key facts

| Fact | Detail | Source |
|---|---|---|
| try requirements | At least one catch or a finally; at most one finally | [Exception Statements](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_statements.htm) |
| Catch order | First matching catch runs; general Exception must be last | [Exception Statements](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_statements.htm) |
| finally | Runs whether or not an exception was thrown, whatever its type | [Exception Statements](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_statements.htm) |
| Uncatchable | LimitException, failed assertions, license exceptions; catch and finally don't run | [Exception Statements](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_statements.htm) |
| Custom exception rules | Extends Exception; name ends with Exception | [Create Custom Exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_custom.htm) |
| Custom constructors | Inherited: none, message, cause, or message plus cause | [Create Custom Exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_custom.htm) |
| Zero rows into one sObject | QueryException "List has no rows for assignment to SObject" | [Built-In Exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_builtin.htm) |
| DmlException detail | `getNumDml()`, `getDmlMessage(i)`, `getDmlFieldNames(i)` | [Built-In Exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_builtin.htm) |
| Unhandled exception | DML already processed is rolled back; email sent | [Exceptions in Apex](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_definition.htm) |
| allOrNone default | true: the Database method behaves like the DML statement | [Manipulate Records with DML](https://trailhead.salesforce.com/content/learn/modules/apex_database/apex_database_dml) |
| addError from API bulk call | Bad records set aside; the rest saved | [Trigger Exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_exceptions.htm) |

## Check yourself

- Why must a catch for DmlException come before a catch for Exception?
- When does a finally block not run?
- Which two rules make a class a valid custom exception?
- Why does addError in a trigger fired by a bulk API load still let valid records save?

## Sources

- [Exceptions in Apex](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_definition.htm)
- [Exception Statements](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_statements.htm)
- [Exception Handling Example](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_trycatch_example.htm)
- [Create Custom Exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_custom.htm)
- [Built-In Exceptions and Common Methods](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_builtin.htm)
- [Exception Class and Built-In Exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_classes_exception_methods.htm)
- [Trigger Exceptions](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_exceptions.htm)
- [Bulk DML Exception Handling](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_dml_bulk_exceptions.htm)
- [Manipulate Records with DML](https://trailhead.salesforce.com/content/learn/modules/apex_database/apex_database_dml)
- [Transaction Control](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_transaction_control.htm)
- [SObject Class](https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_methods_system_sobject.htm)

## About the full unit

The "Core concepts", "Exam traps" and "Worked scenario" sections of this unit, its 9 linked practice questions, and unlimited timed mock exams are included with the Platform Developer pack (USD $19): https://www.certifyforce.com/practice-exams
