DML currently not allowed

This almost belongs in my sarcastically titled, “Meaningful Error Messages ..” series, but as it has traceable causes, I thought I’d write something up on its most frequent causes (I meant to write this up a few months ago, but it slipped my mind (find it in your heart to forgive an ol’ developer) and now I think it’s time the world knew).

‘DML currently not allowed’, what could that mean? Well it means that DML isn’t allowed. And that it’s not allowed right now, but with the slight promise that given time, it will be allowed. Often in the past, hoping against hope, I kept on pressing that button/link/onclick-area, but the cloud never changed its mind. With a sigh I constructed the Google search query and began trundling through the results.

Strangely enough I’ve found myself in similar situations a few times, but with a different source and solution each time. So now let’s try, you and I, to write-up a nice, consolidated list of the whys-and-hows of ‘DML currently not allowed’.

Situations that may cause ‘DML currently not allowed’

  1. Venturing a DML operation within a component controller.
  2. Set in motion a DML operation within a class constructor.
  3. Undertaking a DML operation within a getter or setter.

A short time in the past, I wanted to write my own debugger within Apex, something similar to log4j (I have big love for that logger).

Alas alack,

it could not be,

mainly because,

of points 2 and 3.

– Wes

Don’t judge me because I wax lyrical.  So about those situations..

Fixing previously mentioned situations

  1. This one is surprisingly easy to fix. There is a VisualForce component attribute that can be set such that DML is allowed within its controller i.e. <apex:component allowDml="true" ../>
  2. This one is a bit trickier. Often you need some sort of DML to occur on a page-load, so you try to schtuck it into the controller constructor.. but that ain’t gonna work. I would suggest in most cases that you use the ‘action’ attribute on the tag i.e. <apex:page action="{!doStuff}" .. />. This method will run after the constructor and work in the same way as all other action methods.
  3. In my opinion, this is the trickiest one of all, and it’s a doozy… especially for developers who’ve worked in other OOP languages. The problem here is that only action methods can be used to perform DML. What about DML with getters and setters? No can do. With VisualForce driven by Apex your mindset has to shift, and you need to think of methods as belonging to two broad categories, action methods, and data methods. You should only be performing DML in action methods (those guys that do stuff and return PageReferences or Void), and use data methods to pass object and variable values around.

In the dark recesses of my mind there’s a whisper of a memory of similar errors happening if you get your trigger -> callout -> DML operation in the wrong order. But I’m (mostly) certain that this results in a ‘You have uncommitted work pending. Please commit or rollback before calling out’ error, so that resolution doesn’t belong here.

That’s all I have on this topic, maybe you have another point I’ve missed. If so, I’d be rather happy if you shared it.

16 thoughts on “DML currently not allowed”

  1. You cant NOT update a user record and a data record in the same transaction, you will get a mixed dml statement, because a user record is treated as metadata

    Reply
  2. Wes,

    I’ve been struggling this one for a while and appreciate someone else’s frustration with it. But you left out the “best” part (unless I missed the mention) – You cannot trap this exception at runtime. Which makes writing your code to take an alternate path challenging. We have created an ExceptionHandling.cls that logs unexpected errors to a custom object in order to notify a developer and for proactive defect tracking and resolution purposes. So we get this “DML currently not allowed” error at runtime because of the exception logging.

    I logged a case with Premier Tech Support on this issue hoping that it might become trappable in the future or to provide a list of areas that this exception may occur so we can avoid them.

    Thanks,
    Mike

    Reply
  3. “Well it means that DML isn’t allowed. And that it’s not allowed right now, but with the slight promise that given time, it will be allowed. Often in the past, hoping against hope, I kept on pressing that button/link/onclick-area, but the cloud never changed it’s mind”

    This was me last night 🙂

    Reply
  4. Having exhausted my reportoire of rude words on situations 2 and 3 in my code, I thank you from the bottom of the swear box for this article.

    I would like to add, as this is the first helpful article in the google results (hello future readers, read xkcd) that some page load actions happen twice, especially where PDF rendering a page is concerned, so you will need to check if you’ve done your action before.

    Reply
  5. Hi,

    If this error is occur while updating a record using update record component in flow, what we need to do to resolve this? Please share your thoughts.

    Thanks in advance!

    Reply

Leave a Comment