Bypassing
Switch handlers off from Apex for one transaction, org-wide with custom metadata, or from the handler with Bypassable. Only Trigger Lib handlers are skipped: flows, validation rules and other triggers still run.
From Apex
TriggerOrchestrator.bypass() switches off an object, an orchestrator, a handler class in every context, or every run:
TriggerOrchestrator.bypass().sObject(Contact.SObjectType).handler(AccountOwnerTransferWriter.class);
try {
update accounts;
} finally {
TriggerOrchestrator.bypass().clear();
}- Set it before the DML. It lasts until
clear()or the end of the transaction, nested saves included. - One transaction only. A Queueable, a future method or the next batch
executestarts without bypasses.
From Custom Metadata
Check Bypass__c on a TriggerObject__mdt record to switch off every handler on an object for every user, or on a TriggerHandler__mdt record under it to switch off one class. Changes apply from the next transaction. Fields, deployment and test mocks: Custom Metadata.
From the Handler
Implement the context's Bypassable. bypassOn<Ctx>When() runs once per handler per run and takes no records. When it returns true, the handler is skipped for that run.
public with sharing class ContactReachabilityValidator implements BeforeInsert.Validator, BeforeInsert.Bypassable {
public static Boolean isBypassed = false;
public Boolean bypassOnBeforeInsertWhen() {
return ContactReachabilityValidator.isBypassed || System.isBatch();
}
public Boolean addErrorOnBeforeInsertWhen(TriggerTypes.InsertRecord record) {
return record.isBlank(Contact.Email) && record.isBlank(Contact.Phone) && record.isBlank(Contact.MobilePhone);
}
public void addErrorOnBeforeInsert(TriggerTypes.RejectableInsertRecord record) {
record.addError('A contact needs at least one way to be reached. Fill in Email, Phone or Mobile.');
}
}- Checked last. The Apex and metadata bypasses win.
- Checked before the first handler runs. A flag set by an earlier handler in the same run applies from the next run.
- One context only. The other bypasses cover every context. To skip a class in one context, use Bypassable or leave it out of that context's list.
- To skip only some records, return false from the predicate instead.
Per User
There is no per-user bypass. Check a custom permission yourself:
public Boolean bypassOnAfterUpdateWhen() {
return FeatureManagement.checkPermission('Bypass_Account_Automation');
}To skip a whole context, return an empty list from <ctx>Handlers() under the same check.
Data Migration
For Data Loader, the Bulk API or an import wizard:
- Check
Bypass__con the object'sTriggerObject__mdtrecord. Create the record if it is missing. - Run the load.
- Uncheck
Bypass__c. - Backfill what the handlers would have done. Nothing re-runs them later.
The bypass affects every user while it is on.
