5

I've already looked through all the related posts and can't find a solution for this error:

Error Occurred: An Apex error occurred: System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out

Here's my situation: I have a FLOW that waits for a platform event, pulls the keyword from the event params, if that keyword is null, it calls an @invokableMethod that calls out to an external API.

The docs all say you can't do a callout before the DML actions, but I'm not doing any DML operations at all. I looked through this list that enumerates other operations that might be construed as DML, but I'm not doing any of those either. I also checked the helper methods I'm calling, no or other commands known to throw this error.

Here's my flow and my code:

enter image description here

public class ARpromptKeyword
{
    @InvocableMethod(label='Send AutoResponse Keyword' description='Needs recipientNumber.')
    public static void sendAutoResponseKeyword(List<String> recipientNumber)
    {
        System.debug('sendAutoResponseKeyword called');
        String FromNumber = TwilioAPI.getFromNumber();

        //instantiate the Twilio REST client
        TwilioRestClient client = TwilioAPI.getDefaultClient();

        Map<String, String> properties = new Map<String, String>{
                'To' => recipientNumber[0],
                'From' => FromNumber,
                'Body' => 'Please enter SERVICE or SALES to chat with a team member.'
        };
        TwilioMessage message = client.getAccount().getMessages().create(properties);
    }
}

Any ideas?


I went back and minimized my flow with no data passing or saving, even to internal flow variables. Nothing but waiting for the platform event, then calling the invokable method with no parameters. I still get the same error.

enter image description here

Now, I'm going to try to think of some simpler invokable method to try as my next test...


Further testing tells me calling an Apex Invokable Method works for something like saving a Contact. It appears that it's the last line of the code in my method, where it does the callout, that the problem occurs.

  • I'm not familiar with the Twilio library, but does the create method on the last line of the Apex create or alter any custom objects that are stored? – Ryan Rudd Jan 25 '18 at 20:14
  • @RyanRudd, no. No DML at all. Just a http callout. – PatMcClellan__c Jan 25 '18 at 22:52
  • A wait element creates a flow interview. After the flow finishes I think this gets deleted. I'm guessing that might count as a DML operation (at least it changes the state of the database). Maybe you could put the call out in a future class to get this working? – Kasper Jan 25 '18 at 23:48
  • @Kasper ... just saw your idea as I was posting my own. I did exactly that. Thanks! – PatMcClellan__c Jan 26 '18 at 0:34
  • 1
    @PatMcClellan - You CAN do a callout BEFORE DML, you CANNOT do a callout AFTER DML. Just wanted to clarify your comment in your question to make sure you stay not he right path – Eric Jan 26 '18 at 7:10
5

Found the answer, I think, or at least a reasonable workaround. I remembered that Triggers can't make callouts -- they can only call an @future method to do so. I wondered if Flows are the same, so I tried the following:

Flow calls an @InvokableMethod, which in turn, calls an @future method to make the callout. It works!

 public class FlowARpromptKeyword
{
    @InvocableMethod(label='Send AutoResponse Keyword' description='Needs recipientNumber.')
    public static void callARpromptKeyword(List<string> recipientNumber)
    {
        ARpromptKeyword.sendAutoResponseKeyword(recipientNumber[0]);
    }
}

And...

public class ARpromptKeyword
{
    @future(callout=true)
    public static void sendAutoResponseKeyword(String recipientNumber)
    {
        String FromNumber = TwilioAPI.getFromNumber();

        //instantiate the Twilio REST client
        TwilioRestClient client = TwilioAPI.getDefaultClient();

        Map<String, String> properties = new Map<String, String>{
                'To' => recipientNumber,
                'From' => FromNumber,
                'Body' => 'Please enter SERVICE or SALES to chat with a team member.'
        };
        TwilioMessage message = client.getAccount().getMessages().create(properties);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.