Understanding Different Exceptions in Salesforce

UNDERSTANDING DIFFERENT EXCEPTIONS IN SALESFORCE
Chinmaya By Chinmaya
11 Min Read

Introduction

Salesforce provides a robust exception-handling mechanism to ensure applications remain stable and resilient to errors. Exceptions in Salesforce occur when the platform encounters a problem while executing Apex code.

By understanding the types of exceptions, developers can write better error-handling logic and create more reliable applications.

In this blog, we’ll cover:

    1. What are Exceptions?
    2. Different types of Salesforce exceptions.
    3. Common scenarios where these exceptions occur.
    4. Best practices for handling exceptions.

1. What Are Exceptions?

Exceptions are runtime errors that disrupt the normal flow of code execution. Salesforce exceptions can be broadly categorized into:

    • System Exceptions: Raised by Salesforce when a system-level error occurs.
    • Custom Exceptions: User-defined exceptions to handle application-specific errors.

2. Common System Exceptions in Salesforce

Below are the most common system exceptions you might encounter in Salesforce, along with their causes:

2.1. DML Exception

    • Occurs When: Issues arise during Data Manipulation Language (DML) operations like insert, update, delete, or undelete.
    • Example:
      • Trying to update a record without proper field access.
      • Violating a validation rule.
				
					try {
    Account acc = new Account(Name = null); // Name is a required field
    insert acc;
} catch (DmlException e) {
    System.debug('DML Exception: ' + e.getMessage());
}
				
			

2.2. QueryException

Occurs When: Issues occur with SOQL or SOSL queries.

Example:

    • Query returns no rows (List has no rows for assignment).
    • Query retrieves too many rows, exceeding the governor limit.
				
					try {
    Account acc = [SELECT Id FROM Account WHERE Name = 'NonExistent'];
} catch (QueryException e) {
    System.debug('Query Exception: ' + e.getMessage());
}
				
			

2.3 NullPointerException

Occurs When: Code attempts to access a property or method of a null object.

Example:

    • Referencing an object that hasn’t been initialized.
				
					try {
    Account acc = null;
    System.debug(acc.Name); // Throws NullPointerException
} catch (NullPointerException e) {
    System.debug('Null Pointer Exception: ' + e.getMessage());
}
				
			

2.4. LimitException

Occurs When: Salesforce governor limits are exceeded.

Example:

    • Exceeding SOQL query limits or DML statement limits.
				
					try {
    for (Integer i = 0; i < 150; i++) {
        List<Account> accounts = [SELECT Id FROM Account]; // Exceeds 100 SOQL queries
    }
} catch (LimitException e) {
    System.debug('Limit Exception: ' + e.getMessage());
}
				
			

2.5. Mixed DML Exception

What It Is:

The MixedDmlException occurs when your code tries to perform DML operations on setup objects (like User, Group, or PermissionSet) and non-setup objects (like Account or Contact) in the same transaction.

Why It Happens:

Salesforce separates setup and non-setup objects to ensure platform integrity. Performing DML operations on both in a single transaction violates this constraint.

Example:

				
					try {
    User newUser = new User(Username = 'testuser@example.com', LastName = 'Test', Alias = 'test', Email = 'testuser@example.com', ProfileId = '00e1k0000012345', TimeZoneSidKey = 'America/New_York', LocaleSidKey = 'en_US', EmailEncodingKey = 'UTF-8', LanguageLocaleKey = 'en_US');
    insert newUser;

    Account acc = new Account(Name = 'Test Account');
    insert acc; // Throws MixedDmlException
} catch (MixedDmlException e) {
    System.debug('Mixed DML Exception: ' + e.getMessage());
}
				
			

Solution:

Use asynchronous methods like Future or Queueable Apex to separate the operations:

				
					@future
public static void insertAccountAsync(Account acc) {
    insert acc;
}
				
			

2.6. System.FinalException

What It Is:

The System.FinalException occurs when your code tries to override or bypass a final variable or method. In Salesforce, final variables are immutable, meaning their values cannot be changed once set.

Why It Happens:

This typically happens when attempting to modify the value of a variable declared as final.

Example:

				
					public class FinalExample {
    public final String message = 'Immutable';

    public void updateMessage() {
        message = 'Updated'; // Throws System.FinalException
    }
}
				
			

Solution:

    • Avoid modifying final variables or methods.
    • If mutability is required, use regular variables instead of final.

2.7 Too Many DML Statements

What It Is:

The TooManyDmlStatements exception occurs when your code exceeds the governor limit of 150 DML statements in a single transaction.

Why It Happens:

This typically happens when performing DML operations (like insert, update, or delete) inside loops or in large-scale operations without bulkifying the code.

Example:

				
					try {
    for (Integer i = 0; i < 200; i++) {
        Account acc = new Account(Name = 'Test ' + i);
        insert acc; // Exceeds the 150 DML statements limit
    }
} catch (Exception e) {
    System.debug('Too Many DML Statements Exception: ' + e.getMessage());
}
				
			

Solution:

    • Bulkify your operations to reduce the number of DML statements:
				
					List<Account> accounts = new List<Account>();
for (Integer i = 0; i < 200; i++) {
    accounts.add(new Account(Name = 'Test ' + i));
}
insert accounts; // One DML statement for all records
				
			

2.8 CPU Time Limit Exceeded Exception

What It Is:

The CpuTimeoutException occurs when the Apex transaction exceeds the CPU time limit:

    • Synchronous transactions: 10 seconds.
    • Asynchronous transactions: 60 seconds.

Why It Happens:

Inefficient code, excessive recursion, or processing large data sets can cause this exception.

Example:

				
					try {
    for (Integer i = 0; i < 1000000; i++) {
        System.debug('Processing: ' + i); // Excessive processing
    }
} catch (Exception e) {
    System.debug('CPU Timeout Exception: ' + e.getMessage());
}
				
			

Solution:

    • Optimize your code to reduce processing time.
    • Use Batch Apex for long-running processes:
    • Reduce the use of System.debug() and avoid nested loops.

				
					global class BatchExample implements Database.Batchable<sObject> {
    global Database.QueryLocator start(Database.BatchableContext context) {
        return Database.getQueryLocator('SELECT Id FROM Account');
    }
    global void execute(Database.BatchableContext context, List<SObject> scope) {
        // Process records in manageable chunks
    }
    global void finish(Database.BatchableContext context) {}
}
				
			

2.9. StringException

Occurs When: Issues arise while working with strings.

Example:

    • Accessing a substring index that is out of bounds.
				
					try {
    String str = 'Salesforce';
    System.debug(str.substring(20)); // Out of bounds
} catch (StringException e) {
    System.debug('String Exception: ' + e.getMessage());
}
				
			

2.10. MathException

Occurs When: Mathematical operations fail.

Example:

    • Dividing by zero.
				
					try {
    Integer result = 5 / 0; // Division by zero
} catch (MathException e) {
    System.debug('Math Exception: ' + e.getMessage());
}
				
			

2.11. TypeException

Occurs When: Type casting fails.

Example:

    • Casting an object to an incompatible type.
				
					try {
    Object obj = new Account();
    Contact con = (Contact) obj; // Incompatible type
} catch (TypeException e) {
    System.debug('Type Exception: ' + e.getMessage());
}
				
			

2.12. JSONException

Occurs When: Issues arise while working with JSON serialization or deserialization.

Example:

    • Trying to deserialize invalid JSON.
				
					try {
    String invalidJson = '{"Name": "Account", "Id": }'; // Malformed JSON
    Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(invalidJson);
} catch (JSONException e) {
    System.debug('JSON Exception: ' + e.getMessage());
}
				
			

2.13. CalloutException

Occurs When: Issues occur during HTTP callouts or external service integrations.

Example:

    • Calling a service that times out.
				
					try {
    HttpRequest req = new HttpRequest();
    req.setEndpoint('https://invalidendpoint.com');
    req.setMethod('GET');
    Http http = new Http();
    HttpResponse res = http.send(req);
} catch (CalloutException e) {
    System.debug('Callout Exception: ' + e.getMessage());
}
				
			

2.14. EmailException

Occurs When: Issues arise while sending emails.

Example:

    • Sending an email with an invalid address.
				
					try {
    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
    email.setToAddresses(new String[] {'invalidemail'});
    Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
} catch (EmailException e) {
    System.debug('Email Exception: ' + e.getMessage());
}
				
			

2.15. FieldIntegrityException

Occurs when invalid data is assigned to a field, such as exceeding field length limits or violating picklist constraints.

Example:

				
					try {
    Account acc = new Account(Name = 'This name exceeds the maximum length for the Name field in Salesforce and will throw an exception.');
    insert acc;
} catch (FieldIntegrityException e) {
    System.debug('Field Integrity Exception: ' + e.getMessage());
}
				
			

2.16 AsyncException

AsyncException occurs when Salesforce faces issues executing asynchronous operations like Future Methods, Batch Apex, Queueable Apex, or Scheduled Jobs.

It ensures platform stability by enforcing execution limits.

Common Causes of AsyncException:

  1. Too Many Asynchronous Jobs: – Maximum 50 asynchronous jobs per transaction.
  2. Duplicate Scheduled Job Names:

  3. Too many batch jobs running
  4. Exceeding number of Future calls.

3. Custom Exceptions

Developers can create their own exceptions for specific use cases. This helps make error handling more descriptive and organized.

				
					public class CustomBusinessException extends Exception {}

try {
    Boolean isValid = false;
    if (!isValid) {
        throw new CustomBusinessException('Business logic failed.');
    }
} catch (CustomBusinessException e) {
    System.debug('Custom Exception: ' + e.getMessage());
}
				
			

4. Best Practices for Handling Exceptions

  1. Use Try-Catch Blocks Wisely:
      • Catch specific exceptions where possible.
      • Avoid catching generic Exception unless necessary.
  2. Log Exceptions:
      • Use custom logging or store exceptions in a custom object for debugging.
  3. Provide Meaningful Error Messages:
      • Include relevant context in exception messages to help with troubleshooting.
  4. Handle Exceptions Gracefully:
      • Display user-friendly error messages in the UI.
      • Avoid exposing sensitive information in error messages.
  5. Plan for Governor Limits:
      • Optimize code to stay within Salesforce governor limits, reducing LimitException occurrences.
  6. Validate Inputs:
      • Prevent exceptions like NullPointerException by validating inputs before use.

Conclusion

Understanding and handling exceptions effectively is critical for developing robust and user-friendly Salesforce applications.

By identifying the root causes of exceptions and following best practices for error handling, developers can ensure smoother operations and better user experiences.

Share This Article
Follow:
Chinmaya is working as a Senior Consultant with a deep expertise in Salesforce. Holding multiple Salesforce certifications, he is dedicated to designing and implementing cutting-edge CRM solutions. As the creator of Writtee.com, Chinmaya shares his knowledge on educational and technological topics, helping others excel in Salesforce and related domains.
2 Comments