Business Errors
Introduction
A business error (called a fault in CMMN) represents an expected exceptional business condition (for example "credit check rejected" or "document not found"), as opposed to a technical failure such as a database outage or a programming bug. Business errors are meant to be modeled and handled as part of the normal flow of a case or process, rather than causing the whole execution to roll back.
Business errors are engine-neutral: the same concept works in both CMMN and BPMN, and a business error can propagate across process/case boundaries. A fault thrown in a child case invoked from a process (or a child process invoked from a case) that is not handled will bubble up to the calling parent, where it can be caught and handled.
Throwing a business error
There are several ways to throw a business error, depending on where you are modeling.
From a script (engine-neutral, recommended)
The flw.error script API throws a business error that is caught by CMMN fault sentries and BPMN error boundary events, so the same script works unchanged in either engine:
// with an error code and a message
flw.error.throwBusinessError("CREDIT_REJECTED", "Credit check was rejected");
// with just an error code
flw.error.throwBusinessError("CREDIT_REJECTED");
From a script (engine-specific)
If a model is intended to run in only one engine, the engine-specific helper is also available:
flw.cmmn.throwFault("CREDIT_REJECTED", "Credit check was rejected");
From a Java delegate
// PlanItemJavaDelegate
throw new CmmnFault("CREDIT_REJECTED", "Credit check was rejected");
Catching a business error in CMMN
When a plan item faults, it transitions from Active to a new Failed state (the fault plan item transition). A fault sentry (a sentry whose onPart listens for the fault standard event of the faulting plan item) can then be used as an entry criterion (or exit criterion) on another plan item to model "on fault, do X", matched by error code:

Cross-engine propagation
An unhandled business error propagates up scope by scope, across engine boundaries, until a handler is found.
| Direction | Child scope | Caught in parent by |
|---|---|---|
| CMMN → CMMN | Case Task | Fault sentry on the Case Task plan item |
| CMMN → BPMN | Case invoked via a BPMN Case Task | Error boundary event on the Case Task |
| BPMN → CMMN | Process invoked via a CMMN Process Task | Fault sentry on the Process Task plan item |
| BPMN → BPMN | Call activity | Error boundary event on the call activity |
Multi-level nesting (e.g. BPMN → CMMN → CMMN) works: the error keeps bubbling until handled.
If a business error reaches the root scope with no handler, an exception will be thrown (with the usual exception semantics such as transaction rollback).