I have built an @InvocableMethod to be used as an action in a Salesforce Flow. It’s basic functionality is to look up some records, saves the result in a List of sObject, then make a call out and process the results. When I added the action to a flow and click the debug button to run it I get the “System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out” error.
But even after adding Database.setSavepoint(), Database.rollback(), and Database.releaseSavepoint() into the invocable method’s code, the flow still generates the same error.
However, running the invocable method’s code outside of a flow, such as via Execute Anonymous, the code runs fine.
Note that
- The callout=true switch has been added to the @InvocableMethod declaration
- The record look up is just that, looks up records but makes no changes to them.
- The first line of the code in the invocable method sets the save point.
- The flow I am testing this action with is kicked off by a time-based trigger. No DML operations are happening before the action executes…at least none that I am initiating.
Here is some code that demonstrates the issue. When run anonymously it will execute fine. When run via a Salesforce Flow the above error is generated.
@InvocableMethod(label='Test Database Rollback with Callout in a Flow' callout=true)
global static List<List<String>> testDatabaseRollback() {
Savepoint sp = Database.setSavepoint();
List<List<String>> rLst = new List<List<String>>{};
List<Account> act = [SELECT Id, Name FROM Account LIMIT 5];
Database.rollback(sp);
Database.releaseSavepoint(sp);
Http http = new Http();
String orgDomain = Url.getOrgDomainUrl().toExternalForm();
String endpoint = orgDomain + '/services/data/v60.0/sobjects/';
String sessionId = 'Bearer ' + UserInfo.getSessionId();
HTTPRequest httpReq = new HTTPRequest();
httpReq.setEndpoint( endpoint );
httpReq.setMethod( 'GET' );
httpReq.setHeader( 'Content-Type', 'application/json; charset=UTF-8' );
httpReq.setHeader( 'Accept', 'application/json' );
httpReq.setHeader( 'Authorization', sessionId );
HTTPResponse resp = http.send( httpReq );
if ( String.isNotBlank( String.valueOf(resp)) ) {
system.debug(resp.getHeaderKeys());
for (String s : resp.getHeaderKeys()) {
system.debug(resp.getHeader(s));
}
system.debug('Response body: ' + resp.getBodyAsBlob().toString());
}
return rLst;
}