This error usually occurs in Salesforce Apex when you try to make an HTTP callout while there is an uncommitted database transaction pending. Salesforce doesn’t allow callouts if there are uncommitted changes in the database to maintain data consistency.
Why Does This Happen?
- You are trying to perform a callout (HTTP request to an external system) inside a transaction that has uncommitted database operations (DML operations like insert, update, or delete).
- Salesforce enforces this restriction to prevent data inconsistencies if the callout fails.
How to Fix It?
1. Move the Callout Before DML Operations
Ensure that the HTTP callout happens before any database changes.
HttpResponse response = makeCallout(); // Perform callout first
if(response.getStatusCode() == 200) {
updateRecord(); // Perform DML after callout
}
2. Use @Future Method
Callouts inside an @future method run asynchronously, avoiding this error.
@future(callout=true)
public static void makeCalloutFuture() {
HttpResponse response = makeCallout();
}
Note: @future methods can’t return values or be chained.
3. Use Queueable Apex for More Flexibility
If you need to handle more complex scenarios, use Queueable Apex instead of @future.
public class CalloutJob implements Queueable, Database.AllowsCallouts {
public void execute(QueueableContext context) {
HttpResponse response = makeCallout();
}
}
This approach allows chaining jobs and handling results better.
Final Thoughts
- Always perform callouts before DML operations when possible.
- Use @future or Queueable Apex if you must make a callout after DML.
- Avoid mixing DML and callouts in the same synchronous transaction.