Intermediate 30 min read

Add Validation in Apex

By the end of this lesson, you'll be able to:

  • Prevent an Opportunity from being marked Closed Won without a positive Amount
  • Use addError() to block a save with a field-level message
  • Explain why this validation belongs in a before trigger, not after

Prerequisites: "Bulkify the Logic"

The validation rule

public void beforeUpdate(List<Opportunity> newOpportunities, Map<Id, Opportunity> oldMap) {
    for (Opportunity opp : newOpportunities) {
        Opportunity oldOpp = oldMap.get(opp.Id);
        Boolean justWon = opp.StageName == 'Closed Won' && oldOpp.StageName != 'Closed Won';

        if (justWon && (opp.Amount == null || opp.Amount <= 0)) {
            opp.Amount.addError('An Opportunity cannot be marked Closed Won without a positive Amount.');
        }
    }
}

addError(), called on the specific field, blocks the entire save and shows the message directly next to that field — a much better user experience than a generic failure, and it prevents exactly the "Closed Won with a blank Amount silently rolls up as 0" scenario this lesson exists to close.

Why this belongs in before, not after

addError() only works meaningfully in a before trigger — calling it in an after trigger doesn't prevent the save, since the record is already saved by the time after runs (Module 24's before/after distinction, once again). This validation needs its own beforeUpdate method on the handler, separate from the rollup logic living in afterUpdate.

Updating the trigger to route both events

trigger OpportunityTrigger on Opportunity (before update, after update) {
    OpportunityTriggerHandler handler = new OpportunityTriggerHandler();

    if (Trigger.isBefore) {
        handler.beforeUpdate(Trigger.new, Trigger.oldMap);
    }
    if (Trigger.isAfter) {
        handler.afterUpdate(Trigger.new, Trigger.oldMap);
    }
}

This is Module 24's "Trigger Framework Fundamentals" routing pattern, now genuinely needed — one trigger, two events, each routed to its own clearly-named handler method.

Exercise

Add a validation that blocks any Opportunity update where StageName is being set to 'Closed Won' but CloseDate is null, using addError() on CloseDate.

Show hint

opp.CloseDate.addError(...)

APEX

Add Validation in Apex Quiz

1. Why must addError() be called in a before trigger to actually block the save?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

A Closed Won Opportunity with no Amount would roll up as 0, silently hiding real revenue — this lesson blocks that scenario at the source with a before-trigger validation.