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."
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.Database.executeBatch() call to reduce the number of records in memory per chunk.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.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.checkHeapSize('constructor1') or checkHeapSize('afterSOQL').i, increment it each iteration, and call: if (Math.mod(i, 1000) == 0) { checkHeapSize('loopIteration'); }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.000383707

We use three kinds of cookies on our websites: required, functional, and advertising. You can choose whether functional and advertising cookies apply. Click on the different cookie categories to find out more about each category and to change the default settings.
Privacy Statement
Required cookies are necessary for basic website functionality. Some examples include: session cookies needed to transmit the website, authentication cookies, and security cookies.
Functional cookies enhance functions, performance, and services on the website. Some examples include: cookies used to analyze site traffic, cookies used for market research, and cookies used to display advertising that is not directed to a particular individual.
Advertising cookies track activity across websites in order to understand a viewer’s interests, and direct them specific marketing. Some examples include: cookies used for remarketing, or interest-based advertising.