I'm trying to clone an Opportunity at before update event of Opportunity. But it throws me error,

Opportunity SyncedQuote field is read only within a trigger

    for(Opportunity oppoFull :listOpp){
        if (!setOppId.contains(oppoFull.Id))
        if (oppoFull.clone__c){
           Opportunity oppoCopy = oppoFull.clone(false,true);


    insert listClonedOpps;

I assumed it's because Opportunity's Synced Quote,

and tried setting oppoCopy.SyncedQuoteId = null;

Not resolved, not sure why this field is READ-ONLY only in trigger, Saw people have done similar triggers with @future methods. Any help on workarounds to resolve it? without an asynchronous method?

Really appreciate any tips, thoughts on this. Thanks!


Got it resolved with following workaround.

Created below 2 methods,

private static String populateOppSelectAllFields(Map<String, Schema.SObjectField> fldObjMap) {
        List<Schema.SObjectField> fldObjMapValues = fldObjMap.values();
        String theQuery = 'SELECT ';
        for(Schema.SObjectField s : fldObjMapValues) {
            if (s.getDescribe().getName()=='SyncedQuoteId')

            if (s.getDescribe().isCreateable()) {
                String theName = s.getDescribe().getName();
                theQuery += theName + ',';
        return theQuery.subString(0, theQuery.length() - 1);

    private static Opportunity cloneOpp(Opportunity opp){
        Opportunity newOpp = new Opportunity();

        Map<String,Object> fieldsMap = opp.getPopulatedFieldsAsMap();

        for(String fld :fieldsMap.keyset()){
            newOpp.put(fld, fieldsMap.get(fld));

        newOpp.Id = null;
        return newOpp;

In Trigger handler code,

Map<String, Schema.SObjectField> fldObjMap = schema.SObjectType.Opportunity.fields.getMap();

        String query = populateOppSelectAllFields(fldObjMap) + ' FROM Opportunity WHERE Id  IN :setOppId ';
        List<Opportunity> listOpp2Clone = Database.query(query);
        Map<Id, Opportunity> mapOpp2Clone = new Map<Id, Opportunity>(listOpp2Clone);

for(Opportunity opp :listOpp){
   Opportunity oppoCopy =  cloneOpp(mapOpp2Clone.get(opp.Id));

insert listClonedOpps;

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.