Error Strategy in Salesforce Apex: Custom Exceptions, Fail-Fast Validation, Correlation IDs & Telemetry
In Salesforce Apex, building a reliable error-handling strategy means doing more than just catching exceptions. You need to:
-
Fail fast to block bad data before it hits the database,
-
Use custom exceptions that make intent clear,
-
Tag each transaction with a correlation ID for traceability, and
-
Emit structured telemetry for real-time observability.
Together, these practices keep your data clean, make failures understandable for users, and give your ops team immediate visibility from the UI to the logs and event stream.
? 1) Fail-Fast Validation — Stop Bad Data Early
What & Why:
Validate data before any DML or callouts. Failing fast avoids partial writes, wasted governor limits, and data inconsistencies.
Real Example:
If an agent tries to submit an invoice with Amount__c = 0, reject it immediately — don’t wait for a downstream failure.
public with sharing class InvoiceValidator {
public static void validate(Invoice__c inv) {
if (inv == null) throw new AuraHandledException('Invoice payload is required');
if (inv.Amount__c == null || inv.Amount__c <= 0)
throw new AuraHandledException('Amount must be > 0');
if (String.isBlank(inv.CurrencyIsoCode))
throw new AuraHandledException('Currency is required');
if (String.isBlank(inv.CardLast4__c) || inv.CardLast4__c.length() != 4)
throw new AuraHandledException('card_last4 must be 4 digits');
}
}
? 2) Custom Exceptions — Express Business Intent
What & Why:
Not all failures are system bugs — some are valid business outcomes. Create domain-specific exception classes to separate those from true errors.
Real Example:
If your payment gateway returns “limit exceeded,” throw a PaymentDeclinedException so the UI can guide users to retry later instead of showing a generic error.
? 3) Correlation IDs — Trace a Request End-to-End
What & Why:
Attach a unique correlation ID (like Limits.getRequestId()) to every transaction. Include it in logs, platform events, and API responses. When a customer reports an issue, your ops team can jump straight to the right record in your logs or telemetry.
Real Example:
Support asks for the correlationId shown in the UI; within seconds, you can find the exact API request and exception in logs.
public with sharing class Correlation {
public static String current() { return Limits.getRequestId(); }
public static void logInfo(String msg, Map<String,Object> fields) {
fields = fields == null ? new Map<String,Object>() : fields;
fields.put('cid', current());
System.debug(LoggingLevel.INFO, JSON.serialize(fields) + ' :: ' + msg);
}
}
? 4) Telemetry via Platform Events — Make Errors Observable
What & Why:
Don’t rely on log scraping. Publish structured Platform Events for real-time monitoring and alerts. This makes your system observable by design.
Real Example:
If PaymentDeclined events spike after a gateway update, you’ll know instantly and can trigger an alert.
Platform Event: Error_Telemetry__e
Fields: CorrelationId__c, ErrorType__c, Message__c, Context__c
? 6) Trigger Handler — Surface Friendly Errors & Emit Telemetry
What & Why:
Catching domain exceptions inside your handler lets you show clear, user-friendly messages while still emitting telemetry for monitoring and analytics.
Real Example:
A nightly job inserts invoices. If some fail, users see clear messages, and ops teams get telemetry events with full context and correlation IDs.
? 7) REST API — Return Status Codes & Correlation IDs
What & Why:
When exposing APIs, always map business outcomes to appropriate HTTP response codes and include the correlation ID in every reply. It keeps client systems, users, and ops all in sync.
Real Example:
If a storefront calls /payments and the charge fails, return a 402 status code (Payment Required) with the correlation ID so support can trace it.


