function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ch ranjithch ranjith 

Record is read-only: Trigger.vig2: line 7, column 1

rigger vig2 on join_object__c (after insert)
{
list<join_object__c> jcnewlist=new list<join_object__c>();
for(join_object__c jc:trigger.new)
{
  list<join_object__c> jclist=[select id,name,Account__r.name from join_object__c];
   jc.billing_adress__c=jc.Account__r.name;
   jcnewlist.add(jc);


error


Record is read-only: Trigger.vig2: line 7, column 1
Best Answer chosen by ch ranjith
magicforce9magicforce9
Hi Ranjith,

You second trigger is running under 'After Insert' context but on line #4, you are checking if this is being execulted in 'update' context...hence the logic in inside your if condition will never get executed untill you add 'update' context to the trigger. I'm assuming you want to update the Contacts mailingstreet using the relationship on that junction object and for which I don't think you need another trigger. I have made changes to the first trigger, so the same trigger will the do the job.
trigger vig2 on join_object__c (before insert, before update)
{
    Set<id> accountIds = new Set<id>();
    Set<id> contactIds = new Set<id>();
    for(join_object__c jc:trigger.new)
    {
        if(jc.Account__c != null)
            accountIds.add(jc.Account__c);
        if(jc.Contact__c != null && trigger.isInsert || trigger.oldMap.get(jc.id).Contact__c != trigger.newMap.get(jc.id).Contact__c)
            contactIds.add(jc.Contact__c);
    }
    Map<Id, Account> accountsMap = new Map<Id,Account>([select Id,Name,BillingStreet from Account where Id IN :accountIds]);
    for(join_object__c jc:trigger.new){
        jc.billing_adress__c = accountsMap.get(jc.Account__c).BillingStreet;
    }
    List<Contact> contactList = [Select Id, AccountId, MailingStreet from Contact where Id IN :contactIds];
    for(Contact contact : contactList){
        contact.MailingStreet = accountsMap.get(jc.Account__c).BillingStreet;
    }
    update contactList;
}

All Answers

Chamil MadusankaChamil Madusanka
When you are doing an After trigger, Trigger.new is read only. If you want to make changes to it, then it is best to do it in a Before trigger.

And you don't need to update the accounts at the end of the trigger you only need to do  the assignment operation. 

trigger vig2 on join_object__c (before insert)
{
list<join_object__c> jcnewlist=new list<join_object__c>();
for(join_object__c jc:trigger.new)
{
  list<join_object__c> jclist=[select id,name,Account__r.name from join_object__c];
   jc.billing_adress__c=jc.Account__r.name;
   jcnewlist.add(jc);
}

}


magicforce9magicforce9
Hi Ranjith,

In after insert context, trigger.new is read-only, i.e you can't make modification for the records inside trigger.new(even if you loop over it). You'll need to create another instance of that object and update it at the end(see my example). Also I have noticed that you've used a SOQL query inside for loop, so its possible to hit the governor limit for number of SOQL's in a transaction. You'll need to take he query out of for loop and bulkify your trigger...Read more here : https://developer.salesforce.com/page/Best_Practice%3A_Bulkify_Your_Code
rigger vig2 on join_object__c (after insert)
{
list<join_object__c> jcnewlist=new list<join_object__c>();
for(join_object__c jc:trigger.new)
{
  list<join_object__c> jclist=[select id,name,Account__r.name from join_object__c];
   join_object__c obj = new join_object__c(id = jc.id, billing_adress__c=jc.Account__r.name);
   jcnewlist.add(obj);
// Some more logic you may have
}
if(!jcnewlist.isEmpty()) update jcnewlist;
}
Thanks,
Mohammed
ch ranjithch ranjith
Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger vig20 caused an unexpected exception, contact your administrator: vig20: execution of BeforeInsert caused by: System.DmlException: Update failed. First exception on row 0; first error: MISSING_ARGUMENT, Id not specified in an update call: []: Trigger.vig20: line 13, column 1
ch ranjithch ranjith
I have junction object which relates to account and contact. Whenever new record is inserted in junction object  the account billing street need to be copied in contact mailing street . I tried this but its not working
magicforce9magicforce9
Hi Ranjith,

If you have join_object__c as junction object and all you need is "account billing street need to be copied in contact mailing street", then you can do the same by using a Wokflow field update.

Add a workflow on join_object__c object for "Every time the record is created", put the enry crieeria to "CreatedDate != null!" and then add a Workflow field update action - here in the Field Update you can specify to update the field using a Formula and you can get the field from Account object.

However if you still insist on using a trigger then the code below should help...since its  before insert trigger you don't have to do a DML at the end
trigger vig2 on join_object__c (before insert)
{
	Set<id> accountIds = new Set<id>();
	for(join_object__c jc:trigger.new)
	{
		if(jc.Account__c != null)
			accountIds.add(jc.Account__c);
	}
	Map<Id, Account> accountsMap = new Map<Id,Account>([select Id,Name,BillingStreet from Account where Id IN :accountIds]);
	for(join_object__c jc:trigger.new){
		jc.billing_adress__c = accountsMap.get(jc.Account__c).BillingStreet;
	}
}

ch ranjithch ranjith
I have junction object which relates to account and contact. Whenever new record is inserted in junction object the account billing street need to be copied in contact mailing street . I tried this but its not working

trigger copystreetaddress on Join_object__c(after insert)
{
list<contact> conlist=new list<contact>();   
    if(trigger.isUpdate)
    {
        Set<Id> accountId = new Set<Id>();
        Set<Id> contactId = new Set<Id>();
        for(Join_object__c tempJ : Trigger.new)
        {
            accountId.add(tempJ.Account__c);
            contactId.add(tempJ.Contact__c);
        }
      
        List<Account> AccountList = [Select id,Name,BillingStreet from Account where id in: accountId];
      
        List<Contact> ContactList = [Select id,Name,mailingStreet from Contact where id in: contactId];
      
        for(Join_object__c tempJ : Trigger.new)
        {
            for(Account tempAcc : AccountList)
            {
                if(tempJ.Account__c == tempAcc.Id)
                {
                    for(Contact tempCon : ContactList)
                    {
                        if(tempJ.Contact__c == tempCon.Id)
                        {
                            tempCon.mailingstreet = tempAcc.BillingStreet;
                            conlist.add(tempcon);
                        }                 
                  
                    }
              
                }
          
            } 
          
        }     
         
    }
     update ConList; 
}
help me in this code also
magicforce9magicforce9
Hi Ranjith,

You second trigger is running under 'After Insert' context but on line #4, you are checking if this is being execulted in 'update' context...hence the logic in inside your if condition will never get executed untill you add 'update' context to the trigger. I'm assuming you want to update the Contacts mailingstreet using the relationship on that junction object and for which I don't think you need another trigger. I have made changes to the first trigger, so the same trigger will the do the job.
trigger vig2 on join_object__c (before insert, before update)
{
    Set<id> accountIds = new Set<id>();
    Set<id> contactIds = new Set<id>();
    for(join_object__c jc:trigger.new)
    {
        if(jc.Account__c != null)
            accountIds.add(jc.Account__c);
        if(jc.Contact__c != null && trigger.isInsert || trigger.oldMap.get(jc.id).Contact__c != trigger.newMap.get(jc.id).Contact__c)
            contactIds.add(jc.Contact__c);
    }
    Map<Id, Account> accountsMap = new Map<Id,Account>([select Id,Name,BillingStreet from Account where Id IN :accountIds]);
    for(join_object__c jc:trigger.new){
        jc.billing_adress__c = accountsMap.get(jc.Account__c).BillingStreet;
    }
    List<Contact> contactList = [Select Id, AccountId, MailingStreet from Contact where Id IN :contactIds];
    for(Contact contact : contactList){
        contact.MailingStreet = accountsMap.get(jc.Account__c).BillingStreet;
    }
    update contactList;
}

This was selected as the best answer