One of the approaches could be to listen for errors which are happening in your main object trigger on DML statement, and in case if there are any -- do addError on corresponding parent record.
For example, let's assume the following trigger code, used to update contact last name based on account name:
trigger tr_Account on Account (after update) {
List<Contact> child_contacts =
[SELECT Id, LastName
FROM Contact
WHERE AccountId in :(List<Account>) Trigger.new];
Map<Id, List<Contact>> contacts_by_account = new Map<Id, List<Contact>>();
for(Contact c : child_contacts) {
if (!contacts_by_account.containsKey(c.AccountId)) {
contacts_by_account.put(c.AccountId, new List<Contact>());
}
contacts_by_account.get(c.AccountId).add(c);
}
List<Contact> contacts_to_update = new List<Contact>();
for(Account a : (List<Account>) Trigger.new) {
List<Contact> contacts_to_process = contacts_by_account.get(a.Id);
if (contacts_to_process != null) {
for(Contact c : contacts_to_process) {
if (c.LastName != a.Name) {
c.LastName = a.Name;
contacts_to_update.add(c);
}
}
}
}
update contacts_to_update;
}
In the given scenario, if there is an error on the last line (update contacts_to_update), it will stop entire transaction in order since that will be treated as Exception. Exactly that kind of message is visible in your screenshot. In order to ensure that your DML does not throw an exception, explicit Database.update(list,all_or_none);
method might be used. Consider following example as instead of update contacts_to_update;
:
Integer counter = 0;
List<Database.SaveResult> results = Database.update(contacts_to_update, true);//or false in order to support partial DML nicely
for(Database.SaveResult sr : results) {
if (!sr.isSuccess()) {
//Take only first error for demo purpose
String error_message = 'Issue with Contact Update: '
+ sr.getErrors().get(0).getMessage();
Id account_id = contacts_to_update.get(i).AccountId;
trigger.newMap.get(account_id).addError(error_message);
}
}
Given code will try to update child contacts first, and in case if there are any kind of errors -- it will collect them and discard corresponding parent account with controlled error.