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
Timothy Wade 18Timothy Wade 18 

Need Help With Error with Apex Triggers

Hello, I am very new to writing Apex triggers and I am practicing. I wrote the following apex trigger:

Basically, what I'm trying to do is the following:

Write a trigger that creates two identical Contacts whenever an Account is created. Make sure both Contacts are associated with the Account. Use any values for the fields on the Contacts - just make sure to use variables when populating the fields of each Contact to make sure they are identical.

rigger CreateIdenticalContacts on Account (after insert) {
    for(Account acc: Trigger.new) {
        Contact con                 =  new Contact();
        con.FirstName          =  'Aki';  
        con.FirstName          = 'Akisey';
        con.LastName           = 'Johnson';
        con.LastName          = 'Johnson';
        con.AccountId           = acc.Id;
        
        insert acc;
    }        
}

Here's my test class:
@isTest
public class IdenticalContactsTest {

    @isTest static void createAccount()  {
        Account acc  = new Account();
        acc.Name                        = 'Test123';
      insert acc;
        
        }
}

Here's the error that I' receiving:

21:41:32:112 FATAL_ERROR System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, CreateIdenticalContacts: execution of AfterInsert

When I run test, I receive 100% code coverage. I even deleted other triggers in my sandbox org to see if the error would go away but it didn't. Any assistance would be greatly appreciated.

Thanks,
Tim
 
ANUTEJANUTEJ (Salesforce Developers) 
Hi Timothy,

Can you try below code and check if it works.

Trigger acctri on account(before insert)
{
if(trigger.isinsert && trigger.isbefore)
{
list<contact> conlist = new list<contact>();
for(account a: trigger.new)
{
Contact con                 =  new Contact();
        con.FirstName          =  'Aki';  
        con.FirstName          = 'Akisey';
        con.LastName           = 'Johnson';
        con.LastName          = 'Johnson';
        con.AccountId           = acc.Id;
conlist.add(con);
}
insert conlist;
}
}

I think what you are doing is that you are insert the account again, you need to add the contact to the list and then insert the new records as a list.

Apart from the above I also found this link which has a similar use case can you please have a look at it once: https://developer.salesforce.com/forums/?id=906F000000092JUIAY

I hope this helps and in case if this does can you please mark this as best answer so that it can be used by others in the future.

Regards,
Anutej.
MoonpieMoonpie
Testing - I tried to reply three times and kept getting a "B2" error....
gibb harrgibb harr
 Nice to see this post here and thanks for sharing this to us. Liteblue USPS Gov helps the employees to stay in touch with their career. It also helps in the career development of the USPS employees and provides access to it. Get Usps liteblue.gov login details here.  https://liteblue.red
 
Timothy Wade 18Timothy Wade 18
Hi Moonpie, are you able to reply now. I'm not getting an error when I reply to the post.
 
Timothy Wade 18Timothy Wade 18
Thanks ANUTEJ,

Can you explain to me the following code in English terms so I can understand what it is doing? 

if(trigger.isinsert && trigger.isbefore)
{
list<contact> conlist = new list<contact>();
for(account a: trigger.new)

Thank You
ANUTEJANUTEJ (Salesforce Developers) 
if(trigger.isinsert && trigger.isbefore) -In this statement we are checking if the context is before insert using the inbuilt context variables.

list<contact> conlist = new list<contact>(); - Here we are creating a new list so that we can perform a bulkified operation in the future, and also to make sure that the governer limits are not hit.

for(account a: trigger.new) - as trigger.new contains all the records of account we are taking one record at a time so that we can check the details create a contact with correct details and then add the contact to the list.

I hope I was able to help.

Just for reference, you can see the below best practices such that the implementation is future proof.

1) One Trigger Per Object
A single Apex Trigger is all you need for one particular object. If you develop multiple Triggers for a single object, you have no way of controlling the order of execution if those Triggers can run in the same contexts

2) Logic-less Triggers
If you write methods in your Triggers, those can’t be exposed for test purposes. You also can’t expose logic to be re-used anywhere else in your org.

3) Context-Specific Handler Methods
Create context-specific handler methods in Trigger handlers

4) Bulkify your Code
Bulkifying Apex code refers to the concept of making sure the code properly handles more than one record at a time.

5) Avoid SOQL Queries or DML statements inside FOR Loops
An individual Apex request gets a maximum of 100 SOQL queries before exceeding that governor limit. So if this trigger is invoked by a batch of more than 100 Account records, the governor limit will throw a runtime exception

6) Using Collections, Streamlining Queries, and Efficient For Loops
It is important to use Apex Collections to efficiently query data and store the data in memory. A combination of using collections and streamlining SOQL queries can substantially help writing efficient Apex code and avoid governor limits

7) Querying Large Data Sets
The total number of records that can be returned by SOQL queries in a request is 50,000. If returning a large set of queries causes you to exceed your heap limit, then a SOQL query for loop must be used instead. It can process multiple batches of records through the use of internal calls to query and queryMore

8) Use @future Appropriately
It is critical to write your Apex code to efficiently handle bulk or many records at a time. This is also true for asynchronous Apex methods (those annotated with the @future keyword). The differences between synchronous and asynchronous Apex can be found

9) Avoid Hardcoding IDs
When deploying Apex code between sandbox and production environments, or installing Force.com AppExchange packages, it is essential to avoid hardcoding IDs in the Apex code. By doing so, if the record IDs change between environments, the logic can dynamically identify the proper data to operate against and not fail.

Few more Best Practices for Triggers
There should only be one trigger for each object.
Avoid complex logic in triggers. To simplify testing and resuse, triggers should delegate to Apex classes which contain the actual execution logic. See Mike Leach's excellent trigger template for more info.
Bulkify any "helper" classes and/or methods.
Trigers should be "bulkified" and be able to process up to 200 records for each call.
Execute DML statements using collections instead of individual records per DML statement.
Use Collections in SOQL "WHERE" clauses to retrieve all records back in single query
Use a consistent naming convention including the object name (e.g., AccountTrigger)

I found the above best practices in this link -https://developer.salesforce.com/forums/?id=906F0000000DBl8IAG

Hope this was useful.
MoonpieMoonpie
Hi Tim,

It appears that I am able to reply in general, but some part of the reply I am attempting to post is causing this error:

The operation is not permitted. If you received this in error, please contact info@developerforce.com (code: B2)

But that is such a non-user friendly error, and I have no idea what operation I am attempting that is not permitted.

I was trying to include a link, but I've done that plenty of times before.
MoonpieMoonpie
[Trying yet again, posting a little at a time....]

Hi Tim,

Firstly, when you post code here please do the following:

Click the <> button (highlighted below) at the top of your reply box.
User-added image

Then paste your code inside the popup text box.
User-added image

That makes it MUCH easier to read and follow, and it gives your code line numbers that anyone helping can use for reference.
 
MoonpieMoonpie
OK, so that was obviously not the operation that is not permitted....
Timothy Wade 18Timothy Wade 18
Thanks Moonpie, I will do that in the future. 
MoonpieMoonpie
Secondly, that looks like a homework problem to me.  So rather than give you a direct answer, here is a question to make you look closely and think:

Your problem states to create two Contacts when you create an Account.  What type of record are you creating in your trigger code?

(Once you've determined that, if you want to know why your original code was erroring, please read the There are two types of triggers paragraph - especially the last sentence of the second bulleted point - of the first page of Triggers section of the Apex Developer Guide (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers.htm?search_text=triggers).)

Please let us know if you get it working or you need more help.

All the best!
MoonpieMoonpie
WOW!  The operation is not permitted error was because I was trying to use the word
f i s h

(I was trying to use a form of the saying: 'Give a man a  f i s h  and he will eat for a day; teach him to  f i s h  and he will eat for a lifetime.")

Does anyone know why that word is not allowed?
Timothy Wade 18Timothy Wade 18
Hi Moonpie,

So basically after reviewing your comment and reviewing the link you provided, I changed my trigger from an after trigger to a before trigger and my test class worked as perfectly with 100% code coverage and no error. Wow...I went through all of that trouble just for using the wrong type of event. 
MoonpieMoonpie
Tim,

Just because you are not getting errors and are getting 100% code coverage, does not mean your code is necessarily doing what you think it is or want it to.

There are a number of issues and potential improvements I see to the original code you posted.

Would you please post the most updated version of your code?
SSP AdminSSP Admin
Hi Timothy,
It looks like our team of experts can help you resolve this ticket. We have Salesforce global help-desk support and you can log a case and our Customer Success Agents will help you solve this issue. You can also speak to them on live chat. Click on the below link to contact our help-desk. Trust me it is a support service that we are offering for free!
https://jbshelpdesk.secure.force.com

Thanks,
Jarvis SFDC team
ANUTEJANUTEJ (Salesforce Developers) 
Hi Timothy,

In case if your query is addressed can you please choose the best answer so that it can be used by others in the future if they face a similar issue.

Regards,
Anutej
Timothy Wade 18Timothy Wade 18
So after reviewing my code, I took a step back to analyze the code I wrote earlier and decide to rework it. After reworking the code and thinking through what I was trying to accomplish, I ended up with the following code that worked. I even created a third identical record just for fun. 
 
trigger CreateIdenticalContacts on Account (after insert) {
	List<Contact> con		      =  new List<Contact>();
    for(Account acc: Trigger.new) {
        
        Contact Cont = new Contact();   
        cont.AccountiD     = acc.id;
        cont.FirstName     = 'Akisey';
        cont.LastName      = 'Johnson';
        
        con.add(Cont);
        
        Contact C1 = new Contact();
        C1.AccountID = acc.id;
        C1.FirstName = 'Aki';
        C1.LastName = 'Johnson';
                
        con.add(C1);
        
        Contact C2 = new Contact();
        C2.AccountId = acc.id;
        C2.FirstName = 'Akia';
        C2.LastName = 'Johnson';
        
        con.add(C2);               
        
}
        insert con; 
       
    }
Thanks for all the help and guidance. I appreciate it.

Tim
ANUTEJANUTEJ (Salesforce Developers) 
Awesome Tim, nice work on writing a fine trigger.

If possible can you try choosing the best answer so that it can be useful for others and also it would help in keeping the community clean, hope you understand.

Regards,
Anutej