DUPLICATE_VALUE: duplicate value found
You tried to insert or update a record with a value on a unique field (External ID set to "Unique" or one of the unique standard fields like User.Username) that already exists on another record. The fix is either to use a different value, upsert via the External ID, or merge the duplicate.
Also seen asDUPLICATE_VALUE·duplicate value found·DUPLICATE_VALUE: duplicate value found·duplicate value on record
Salesforce enforces uniqueness on three categories of fields:
| Field | Where defined |
|---|---|
External ID custom fields with the Unique checkbox | Custom field setup |
Standard fields like User.Username, User.Email, Account.AccountNumber | Built into the standard objects |
| Fields with the Case-sensitive unique constraint | Custom field setup |
When a save tries to write a value that already exists on another record, you get DUPLICATE_VALUE.
Fix 1: use Upsert instead of Insert
If your intent is "create or update by External ID," use upsert keyed on the unique field:
Contact c = new Contact(LastName = 'Smith', Email = 'a@b.com', External_Id__c = 'CRM-123');
upsert c External_Id__c; // creates if no match, updates if matched on External_Id__c
upsert looks up the row by the external ID, and either inserts or updates appropriately. No DUPLICATE_VALUE because the platform handles the matching.
Fix 2: query before you insert
If your code can't know whether the row exists, query first:
List<Contact> existing = [
SELECT Id FROM Contact WHERE External_Id__c = :ext LIMIT 1
];
if (existing.isEmpty()) {
insert new Contact(External_Id__c = ext, ...);
} else {
Contact c = existing[0];
c.Name = ...;
update c;
}
This is fine for low-volume cases. For high-volume, use the upsert pattern instead — it's one round trip vs two.
Fix 3: the dedupe matching rules
Some DUPLICATE_VALUE errors come from Duplicate Rules, not from a unique-field constraint. These rules can block creation of records that fuzzy-match an existing one (Same Name + Same Phone, etc.).
The error format is different:
DUPLICATE_VALUE: duplicate detected; matched: 0036x...
The matched ID is the existing record. You can:
- Edit the duplicate rule (Setup → Duplicate Rules) to allow the operation.
- Use the
Database.insert(records, dmlOptions)overload withDuplicateRuleHeader.allowSave = true:Database.DMLOptions opts = new Database.DMLOptions(); opts.duplicateRuleHeader.allowSave = true; Database.insert(records, opts); - Merge the duplicates after detection.
Fix 4: case-sensitive vs case-insensitive
A custom unique field's "Case Sensitive" toggle changes the meaning of duplicate. With it off, Acme and ACME collide; with it on, they don't. If your data has both casings and the field is case-insensitive, you'll get duplicates that look like genuine new records to the user. Either toggle the case sensitivity or normalise upstream.
Standard fields that get this wrong
User.Username is unique across all of Salesforce, not just your org. So cooldipojjal@gmail.com is taken globally — pick a unique format like cooldipojjal+myorg@gmail.com. User.Email is unique only within the org by default, but org-wide uniqueness can be toggled in security settings.
