ROUTINE-LEVEL ON ERROR UNDO, THROW statement

Use this statement in a procedure (.p) or class (.cls) file to change the implicit, default ON ERROR directive from UNDO, RETRY to UNDO, THROW for all routine-level blocks in a file. This is specifically for ERROR, not STOP conditions because STOP conditions are already thrown by default. The statement must come before any executable or DEFINE statements in a file. However, it can come either before or after a USING statement. In a .cls file, the statement must come before the CLASS statement.

Syntax

ROUTINE-LEVEL ON ERROR UNDO, THROW.

The following blocks are the routine-level blocks affected by this statement:

  • Procedure (also called main block, external procedure, or .p file, including database trigger .p files)
  • Internal procedures
  • User-defined functions
  • Methods of a class
  • Class constructors
  • Property accessors
  • ON blocks used as database triggers with CREATE, DELETE, WRITE or ASSIGN events

This statement does not affect:

  • Destructors
  • DO, FOR, or REPEAT blocks contained within the routine-level blocks
  • ON blocks that are UI triggers.

Note these alternatives to the ROUTINE-LEVEL ON ERROR UNDO, THROW statement:

  • Instead of adding the statement to source-code files, you can use the -undothrow 1 startup parameter to change the default error handling on routine-level blocks to UNDO, THROW during compilation. See the Startup Command and Parameter Reference for more information.
  • The BLOCK-LEVEL ON ERROR UNDO, THROW statement can be used if you want to change the default error handling on REPEAT, FOR, and DO TRANSACTION blocks in addition to routine-level blocks. (You can use the -undothrow 2 startup parameter to change the default error-handling to UNDO, THROW on every block affected by the BLOCK-LEVEL statement during compilation.)

Example

This code propagates an error from an internal procedures up to the main procedure block.

r-ROUTINE-LEVEL-01.p

ROUTINE-LEVEL ON ERROR UNDO, THROW.

PROCEDURE find1000:
  FIND FIRST Customer WHERE Customer.CustNum = 1000.
END PROCEDURE.

PROCEDURE find2000:
  FIND FIRST Customer WHERE Customer.CustNum = 2000.
END PROCEDURE.

PROCEDURE find3000:
  FIND FIRST Customer WHERE Customer.CustNum = 3000.
END PROCEDURE.

/* Main Block */
RUN find1000.
RUN find2000.
RUN find3000.

CATCH eAnyError AS Progress.Lang.SysError:
  MESSAGE "Your CATCH block associated with the the main block (.p) has handled an error in an internal procedure."
    VIEW-AS ALERT-BOX BUTTONS OK.
END CATCH.

Notes

  • The ROUTINE-LEVEL ON ERROR UNDO, THROW statement guarantees that all unhandled errors in a subprocedure of a persistent procedure, or method of a class, are propagated up to the caller. You decide for each subprocedure, or method within the file, whether that subprocedure or method should handle errors with its own CATCH block. Alternatively, you may want a CATCH block at the caller level to handle errors. This can be useful if a caller calls many internal procedures in a persistent procedure or many methods in a class.
  • You cannot change the default behavior for individual routine-level blocks to throw or rethrow errors.
  • Error objects can be thrown from an application server and handled by a CATCH block on an ABL client. To be throwable from an application server to an ABL client, user-defined error classes must be defined on both the server and client sides, and the classes must be defined as SERIALIZABLE. For the full list of restrictions on class-based objects that are passed between application server and client, see the Parameter passing syntax entry. For more information on error handling in general, see ABL Error Handling.

See also

BLOCK-LEVEL ON ERROR UNDO, THROW statement, ON ENDKEY phrase, ON ERROR phrase, ON QUIT phrase, RETURN statement, RETURN-VALUE function, STOP statement, UNDO-THROW-SCOPE attribute