Try OpenEdge Now
skip to main content
Error Handling
Handling Errors with CATCH Blocks : Introduction
 

Introduction

Structured error handling allows you to provide custom error-handling code for any type of error. ABL provides the CATCH statement to handle specific error types. The CATCH statement defines an end block of code that only executes if the ERROR condition is raised in its associated block and the type of error raised is the error type specified in the CATCH statement (or a subtype of that type). For example:
DO TRANSACTION ON ERROR UNDO, THROW:

FIND FIRST Customer WHERE CustNum=1000.
    RUN CreditCheck.p(Customer.CustNum).

/* CATCH associated with DO TRANSACTION */
CATCH eAppError AS Progress.Lang.AppError:
MESSAGE "This customer is on Credit Hold.".
    END CATCH.
END.

/* CATCH associated with Procedure (Main) block */
CATCH eSysError AS Progress.Lang.SysError:
MESSAGE "Customer record does not exist.".
END CATCH.
In this example, the THROW directive tells the AVM to propagate (pass) any unhandled errors to the procedure (main) block, since the procedure block is the enclosing block of the DO TRANSACTION block. Notice there is a CATCH block waiting to handle any Progress.Lang.AppError object that may get raised from the RUN statement. If a Progress.Lang.AppError object gets raised, the CATCH block handles the error and the error is not passed to the procedure block.
However, when this code runs, it raises a Progress.Lang.SysError because the FIND statement fails and there is no error handler present for this error type. (To handle Progress.Lang.SysError, you could add either a CATCH block for Progress.Lang.SysError or a NO-ERROR option on the FIND statement.) Since Progress.Lang.SysError is not handled, the AVM moves the error up the call stack to the procedure block. The AVM finds a compatible CATCH block on the procedure block and constructs a Progress.Lang.SysError object named eSysError, and then executes the code in the CATCH block. Error objects are deleted automatically by the AVM garbage collection mechanism.
If you delete the CATCH block on the procedure block and run the example code, the AVM propagates the Progress.Lang.SysError object to the main block as before. Since you no longer have an appropriate error handler in the main block, the AVM now executes the default error handling behavior, which is to display the system error message to the default output device.
The CATCH block executes once for each iteration of its associated block that raises a compatible error. A block can have multiple CATCH blocks, and all must come at the end of the associated block.
There can only be one CATCH block for each specific error type in a block. However, a CATCH block for a specific error type will also handle error objects for its subtypes. So, it is possible that there can be more than one CATCH block to handle a particular error type in a block. If multiple CATCH blocks are compatible with the error raised, the AVM will execute the first CATCH block it encounters that is compatible with the error. For this reason, CATCH blocks should be arranged from the most specific error type to the most general error type. For example, if you had different error handling code for Progress.Lang.SysError objects and SoapFaultError objects, you would put the CATCH block for SoapFaultError objects first. Since Progress.Lang.SoapFaultError objects are a subtype of Progress.Lang.SysError objects, a CATCH block for Progress.Lang.SysError objects will also handle Progress.Lang.SoapFaultError objects.