on_exception(-Exception, +*ProtectedGoal, +*Handler)

Specify an exception handler for ProtectedGoal, and call ProtectedGoal.


Exception term
Any term.
ProtectedGoal callable [MOD]
A goal.
Handler callable [MOD]
A goal.


ProtectedGoal is executed. This will behave just as if ProtectedGoal had been written without the on_exception/3 wrapper. If ProtectedGoal is determinate, then on_exception/3 will also be determinate. ProtectedGoal can also be nondeterminate. As a general rule, code is easier to read when ProtectedGoal is a simple goal, however a conjunction of goals (Goal1,...GoalN) or any other form that call/1 accepts is allowed.

If an exception is raised while ProtectedGoal is running, Prolog will abandon ProtectedGoal entirely. Any bindings made by ProtectedGoal will be undone, just as if it had failed. Side effects, such as data-base changes and input/output, are not undone, just as they are not undone when a goal fails. After undoing the bindings, Prolog then tries to unify an object called an exception term with the Exception argument. If this unification succeeds, Handler will be executed as if you had written

         Exception=the actual exception term,

If this unification fails, Prolog will keep looking for a handler. It will always find a handler at the top level, which prints out a message corresponding to the exception.

In applications lacking a top level (C calling Prolog, where QP_toplevel() has not been called) exceptions are indicated by the return status QP_ERROR. For more details refer to fli-ffp.


Same as call/1.


More efficient code is generated when ProtectedGoal is a simple goal. In other cases, such as where ProtectedGoal is a conjunction of goals (Goal1,...GoalN), the compiler treats this as if it were call((Goal1,..., GoalN)). This potential inefficiency does not apply to Handler.


Fail on exception:

     :-meta_predicate fail_on_exception/1.
         format('Exception occured while calling ~q:~n',

See Also

raise_exception/1, print_message/2. ref-ere-hex.