Salesforce Contact触发器遇System.FinalException,自定义报错失效求助
解决Salesforce触发器System.FinalException错误方案
错误原因
你遇到的System.FinalException: SObject row does not allow errors,核心问题是你在查询出来的Contact实例上调用了addError方法。Salesforce规定,只有触发器上下文里的SObject(比如Trigger.new、Trigger.old)才能添加错误提示,直接查询出来的记录是独立副本,不属于触发上下文,因此不允许调用addError。
另外你的代码还有两个潜在问题:
- 触发器中用
[SELECT ... WHERE id IN :Trigger.new]查询返回的是列表,但你用单个Contact变量接收,批量处理时会直接报错 - 处理器是单条记录处理逻辑,不符合Salesforce批量处理的最佳实践,容易触发SOQL查询次数限制
修正后的代码
触发器代码
trigger ContactTrigger on Contact (before update) { if(Trigger.isBefore && Trigger.isUpdate){ ContactTriggerHandler.checkPricingLetterContacts(Trigger.new); } }
处理器代码
public class ContactTriggerHandler { public static void checkPricingLetterContacts(List<Contact> contacts){ // 批量收集所有待处理的Contact ID Set<Id> contactIds = new Set<Id>(); for(Contact con : contacts){ contactIds.add(con.Id); } // 一次查询所有关联"Pricing Letters"角色的Contact ID Set<Id> pricingLetterContactIds = new Set<Id>(); for(AccountContactRelation acr : [SELECT ContactId FROM AccountContactRelation WHERE Roles INCLUDES ('Pricing Letters') AND ContactId IN :contactIds]){ pricingLetterContactIds.add(acr.ContactId); } // 遍历触发上下文的记录,给符合条件的Contact加错误提示 for(Contact con : contacts){ if(pricingLetterContactIds.contains(con.Id)){ if(String.isBlank(con.MailingStreet)){ con.addError('Pricing Letter联系人的邮寄街道不能为空。'); } if(String.isBlank(con.MailingCity)){ con.addError('Pricing Letter联系人的邮寄城市不能为空。'); } if(String.isBlank(con.MailingPostalCode)){ con.addError('Pricing Letter联系人的邮寄邮政编码不能为空。'); } if(String.isBlank(con.MailingState)){ con.addError('Pricing Letter联系人的邮寄州/省不能为空。'); } if(String.isBlank(con.MailingCountry)){ con.addError('Pricing Letter联系人的邮寄国家/地区不能为空。'); } if(String.isBlank(con.Email)){ con.addError('Pricing Letter联系人的邮箱地址不能为空。'); } } } } }
修改说明
- 触发器部分:直接将
Trigger.new传入处理器,确保操作的是触发上下文的记录,避免查询副本导致的错误 - 处理器部分:
- 批量收集Contact ID,一次完成所有关联AccountContactRelation的查询,符合Salesforce governor limits要求
- 用Set存储符合条件的Contact ID,快速判断当前Contact是否属于目标角色
- 替换
==null为String.isBlank(),同时处理空字符串的情况(如用户输入空格) - 支持批量处理多条记录,适配触发器的批量执行场景
内容的提问来源于stack exchange,提问作者RobIsNotATechGuy
相关产品推荐
相关产品推荐

