UNCOMMITTED_WORK PENDING.
Setup and non-Setup DML in the same transaction. Salesforce blocks it for data integrity — many teams discover this in prod.
The rule.
System.DmlException: UNCOMMITTED_WORK_PENDING
You cannot mix Setup objects (User, Profile, PermissionSet) with non-Setup objects (Account, Contact) in the same transaction.
Setup
User, Profile, PermissionSet
Non-Setup
Account, Contact, Opportunity
2 hrs
Average recovery time
Bad vs good.
UserProvisioningService.clsAnti-pattern
// ❌ BAD: Mixed DML operations in same transaction
// Setup objects (User, Profile) mixed with non-Setup (Account)
public void createUserAndAccount() {
// Setup object DML
User newUser = new User(
FirstName = 'John',
LastName = 'Doe',
Email = 'john@example.com',
Username = 'john@example.com',
ProfileId = '00e...'
);
insert newUser; // Setup object
// Non-Setup object DML in same transaction
Account newAccount = new Account(
Name = 'Acme Corp'
);
insert newAccount; // ❌ CRASH!
// System.DmlException: UNCOMMITTED_WORK_PENDING
}UserProvisioningService.clsFixed
// ✅ GOOD: Separate transactions using async
public void createUserAndAccount() {
// Setup object DML in current transaction
User newUser = new User(
FirstName = 'John',
LastName = 'Doe',
Email = 'john@example.com',
Username = 'john@example.com',
ProfileId = '00e...'
);
insert newUser;
// Non-Setup object DML in async transaction
Account newAccount = new Account(
Name = 'Acme Corp'
);
// Use Future method or Queueable
createAccountAsync(newAccount);
}
@future
public static void createAccountAsync(Account acc) {
insert acc; // Separate transaction - no conflict
}The fix.
Split Setup DML into a separate async transaction (@future or Queueable). Jataka detects Setup/non-Setup conflicts during Sandbox execution.
Catch this before production.
Book a pilot and watch Jataka block this exact anti-pattern on your next PR.