OrgReady

Salesforce Skills & Readiness

Learning progress is unavailable. Reading and direct practice remain available; completion controls are disabled.

← Back to Salesforce Development

Lesson 6 of 6 · 5–10 minutes including the walkthrough and reflection

Error Handling & Production Patterns

Production Apex should make failures clear. A user-facing validation problem, a partial data issue, and an unexpected platform exception need different handling, different messages, and different recovery paths.

The concept

Start by separating two kinds of failure. Expected business validation - The user entered data that violates a rule. - The system can explain what to fix. - addError is appropriate when you need to block a DML operation for a specific record in trigger-style validation. Unexpected technical failure - A callout fails. - A query finds data in a shape the code did not expect. - A DML operation fails for a reason your flow did not plan for. - You need useful developer-facing diagnostics without leaking sensitive data to users. All-or-nothing vs partial success: - DML statements such as update records throw an exception when the operation fails. - Database methods can support partial success when called with allOrNone=false, and then you must inspect each SaveResult. - Partial success is only correct when the business process allows independent records to succeed or fail separately. Good production error handling does not mean catch everything. It means the caller receives an honest result and developers have enough safe context to investigate.

Worked example

// ❌ Problematic: hides the failure and tells the caller nothing useful.
try {
    update contactsToUpdate;
} catch (Exception ex) {
    System.debug(ex.getMessage());
}

// ✅ Business validation: block the specific record with a useful message.
for (Account accountRecord : Trigger.new) {
    if (accountRecord.Industry == 'Restricted') {
        accountRecord.addError('Choose an allowed Industry before saving this Account.');
    }
}

// ✅ Partial-success pattern when independent records may succeed separately.
Database.SaveResult[] results = Database.update(contactsToUpdate, false);

for (Integer i = 0; i < results.size(); i++) {
    if (!results[i].isSuccess()) {
        for (Database.Error error : results[i].getErrors()) {
            // Record safe diagnostic context for developers/operators.
            System.debug('Contact update failed: ' + error.getMessage());
        }
    }
}

How to choose the pattern: 1. Is this a business rule the user can fix now? Use a clear validation message. In trigger validation, addError can stop the bad record. 2. Must every record succeed together? Use all-or-nothing behavior. Do not report success if part of the required operation failed. 3. Can each record succeed independently? A Database method with partial success can be appropriate, but only if you inspect failures. 4. What should be logged? Keep developer-facing context useful: operation name, record Id when safe, error message, and a correlation or job reference if available. Do not log secrets or sensitive payloads. ⚠️ A giant catch (Exception ex) block that swallows the exception is not resilience. It removes the signal that something went wrong.

Common mistake

❌ Common mistake: Catching an exception, writing System.debug, and continuing as if the operation succeeded. Another common mistake: Using Database.update(records, false) and never checking SaveResult failures. That can silently lose failed records while the method returns normally.

Interview angle

🎯 Interview angle Question: “How do you handle errors in production Apex?” Weak answer: “I use try/catch.” Stronger answer: “I separate expected business validation from unexpected technical failures. For record validation, I use clear user-facing messages such as addError where appropriate. For DML, I decide whether the business process needs all-or-nothing behavior or partial success with SaveResult inspection. I avoid swallowing exceptions and make sure failures leave safe diagnostic context for support.”

Pause and apply

🧠 Key takeaway: Business validation ↓ Clear user message Technical failure ↓ Honest result + safe diagnostics Partial success ↓ Inspect every SaveResult Try it yourself: 1. When should an Account trigger use addError instead of catching an exception? 2. If 2 of 100 Contact updates fail with allOrNone=false, where will you find those failures? 3. What information helps developers debug without exposing sensitive data? 4. When would partial success be wrong for a business process?

Official references

Reviewed 2026-09-15. Examples are illustrative; no code is executed here.

Apply it in practice

Business Validation with addError

Marking a lesson as read records learning activity, not mastery. Practice evidence continues to come from the challenge system.

Practice without marking read