Loading

Troubleshoot 'System.LimitException: Batchable instance is too big' error

Julkaisupäivä: Apr 24, 2026
Kuvaus

If a Batch Apex class implements Database.Stateful, the instance state is stored in the database between batch chunks. Salesforce checks the size of the instance state at each chunk boundary and throws System.LimitException: Batchable instance is too big when the Apex Heap Size limit is exceeded. The heap size limit is 6 MB for synchronous Apex and 12 MB for asynchronous Apex. This exception commonly occurs when large collections are persistently maintained across batch chunks using Database.Stateful.

Even if some chunks fail with this error, the batch job continues processing remaining chunks. As noted in the Batch Apex Developer Guide: "If the first transaction succeeds but the second fails, the database updates made in the first transaction are not rolled back."

Ratkaisu

Initial Workaround Steps

Before using the debug approach below, try these steps to reduce heap size usage:
  1. Avoid using Database.Stateful — If you do not need to maintain state across batch chunks, remove the Database.Stateful implementation. State will not be preserved, but heap usage per chunk will be minimized.
  2. Reduce the amount of persistent data — Store only the minimum data needed in instance variables. Avoid storing full SObject records; store only the required field values (e.g., IDs).
  3. Process fewer records per batch — Reduce the batch size in the Database.executeBatch() call to reduce the number of records in memory per chunk.

Debugging Heap Size with Debug Logs

If Database.Stateful is required and the steps above do not resolve the issue, use the following debugging approach to identify where the heap size is being exceeded.
Step 1 — Add the following debug method to the affected Batch Apex class:
The checkHeapSize(String tag) method calls system.debug() and logs the current heap size using Limits.getHeapSize() and the limit using Limits.getLimitHeapSize(), with a tag parameter to identify the call location.
Step 2a — Call the method at key points in your code using a descriptive tag so you can identify the location in the debug log. For example: checkHeapSize('constructor1') or checkHeapSize('afterSOQL').
Step 2b — For loops, check every 1000th iteration to track heap growth without flooding the log. Add a local integer variable i, increment it each iteration, and call: if (Math.mod(i, 1000) == 0) { checkHeapSize('loopIteration'); }
Step 3 — Review the debug logs to find where the heap size approaches or exceeds the limit. Note: Testing in Developer Console runs code synchronously and shows a 6 MB limit, but scheduled batch heap limit is the asynchronous limit of 12 MB.
Step 4 — Fix the problematic code section identified in the logs. If heap size does not exceed the limit in logs but the error persists, repeat steps 1–3.

Example of Code That Causes Heap Size Overflow

The following code causes the heap limit to be exceeded because the retryIds Set grows unboundedly. Every matching Process_Error__c record's Asset_Maintenance__c value is added to retryIds in every batch chunk, and because the class is Database.Stateful, this Set accumulates across all chunks. When processing large data volumes, the total size of retryIds exceeds the 12 MB asynchronous heap limit.

retryIds = new Set<String>();
for(Process_Error__c pe : [SELECT Id, Asset_Maintenance__c, AssetId__c, Error_Messages__c, No_of_Retries__c, Is_Successful__c FROM Process_Error__c WHERE Is_Successful__c = FALSE AND Max_Retries_Reached__c = FALSE]){
    ProcessErrorMap.put(pe.AssetId__c, pe);
    if (pe.Asset_Maintenance__c != null) {
        retryIds.add(pe.Asset_Maintenance__c);
    }
}
To fix this, restructure the code to avoid accumulating all values in a persistent collection. Consider processing and clearing the Set within each batch execute chunk rather than accumulating across chunks.
Knowledge-artikkelin numero

000383707

 
Ladataan
Salesforce Help | Article