What else, other than insert/update/upsert/delete, can cause "System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out"? I've search the debug logs multiple times, and there absolutely is not a DML statement executed between the startTest and the failing callout.

Are there any other commands, or perhaps another callout (even though it's only an inquiry), that can cause this? Does anyone know how to get around this problem?

  • 3
    Please share your code and that will take it from a guessing game to a Q&A format. – Adrian Larson Feb 6 '17 at 17:30
  • 2
    Do you have any workflows are getting fired which is sending emails? – Santanu Boral Feb 6 '17 at 17:35
  • Setting savepoints or rolling back to them, basically any asynchronous calls, there are a great many possibilities here. – Adrian Larson Feb 6 '17 at 17:40
  • 1
    Have you read this document, and made sure you followed the rules? All DML must occur before Test.startTest, Test.setMock should be called immediately after Test.startTest, and your callout should be called immediately after that. – sfdcfox Feb 6 '17 at 18:14
  • I'd second @SantanuBoral here... Workflow email alerts (even ones which are triggered in before startTest()) will cause this error. – NSjonas Feb 6 '17 at 18:49

Here is a list of the operations that could possibly count as a DML when executed before a callout:

  • Database methods
    • convertLead
    • delete
    • deleteAsync
    • deleteImmediate
    • emptyRecycleBin
    • executeBatch
    • insert
    • insertAsync
    • insertImmediate
    • merge
    • rollback
    • setSavepoint
    • undelete
    • update
    • updateAsync
    • updateImmediate
    • upsert
  • System methods
    • abortJob
    • enqueueJob
    • movePassword
    • process
    • purgeOldAsyncJobs
    • resetPassword
    • schedule
    • scheduleBatch
    • setPassword
    • submit
  • Messaging methods
    • reserveMassEmailCapacity

Special Case - During tests when object has an email alert

If using API v38 or earlier during test methods when an email alert is set on the object will also produce this error


  • Thanks Adrian. Actually there's one more under messaging, which is the one I was hitting. Here's a discovery: within a test run, the system is looking at the real Limits.getSingleEmailInvocations() and Limits.getLimitSingleEmailInvocations() when trying to send email, even though if you check those values they always return 0 and 10 inside the test, respectively. Since test instances typically only allow 10 emails, this is a serious issue for any code that generates emails. – aging hippie Feb 6 '17 at 19:06
  • 2
    I've made this post a wiki, in case anything was missed. Feel free to add any methods that are not included already. – Adrian Larson Feb 6 '17 at 19:07
  • Thanks for this. After a callout, I was calling a simple Database.executeBatch that contained no explicit DML, inside a class that contained no explicit DML. Took me a day to track this down and (kind of) understand. The basic response of 'Dont do any DML before a Callout' isnt really clear enough for me. Is there any documentation that simply calling methods such as Database.executeBatch will count as a DML? – ATA1k May 2 '18 at 22:01

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.