Monday, August 26, 2013

MIXED_DML_OPERATION: An inconsistent message


FATAL_ERROR|System.DmlException: Insert failed. First exception on row 0; first error: MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): User, original object: Account: []

This is an error on the surface not hard to understand, as numerous blog posts have explained; it means you can't run DML against regular SObjects in the same transaction that also runs DML against setup object (User, Group, Territory, etc.).  The fix for it is kinda odd, but workable: separate the two kinds of DMLs by system.runas(), which provides separate execution context so they don't collide.  If this workaround doesn't bother you enough, there are two other oddities related to the issue that would probably prompt you to say "there's something wrong with this picture":
  • I've yet to see an official documentation of the error - cause, background, and remedy - anywhere.  Not even from someone who's from Salesforce posting on a community place.
  • For test code, the error only shows when it's executed from the UI (Setup page or Developer Console).  It's not a problem if the test is run via IDE (or even during deploy I suspect).
 It's one of those lingering pesky things that bother developers.  I'll keep bugging people from the inside when I get a chance, and call for a celebration when it's fixed.

UPDATE:  Here are the two official links regarding the message: the origin of the error and specifically, how you handle it in a test context.

2 comments:

  1. Did you receive any feedback from inside?

    ReplyDelete
  2. @Богдан Довгань I didn't get any useful feedback from any Salesforce people, but the situation has somewhat improved. There's now official documentation detailing the approach in testing to deal with the problem (http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects_test_methods.htm), and the behavior is now consistent (if you see the error, you'll get it regardless how you run the tests). The only mystery left is, even for situations that supposedly can be addressed by the workaround, sometimes the error still appears. I might document those when I get a chance.

    ReplyDelete