These statements are used to actively signal an exception situation during program execution. You typically do this when:
- An error occurs that the current program unit (method, function module, form routine) cannot resolve itself.
- An unexpected or invalid state is reached.
- A specific business rule is violated.
Raising an exception interrupts the normal program flow at that point and passes control to a special error handling block (CATCH block for class-based exceptions) or to the caller (who then checks sy-subrc for non-class-based exceptions). This enables structured error handling.
There are two main types of exceptions and thus two RAISE variants:
1. Class-based Exceptions (Modern, Preferred!)
This is the standard way in modern, object-oriented ABAP. Exceptions here are objects of special exception classes (that inherit from CX_ROOT).
Syntax
" 1. Raise a new exception of a class:RAISE EXCEPTION TYPE <exception_class> [EXPORTING p1 = v1 p2 = v2 ...] " Pass parameters to constructor [MESSAGE { <msg> " Message from object/interface | ID <id> TYPE <t> NUMBER <n> [WITH v1 v2 v3 v4] " Message from T100 | oref->if_t100_message } ] " Message from another object [USING MESSAGE]. " Use message from TEXTID
" 2. Re-raise an already existing exception object (e.g., in CATCH):RAISE EXCEPTION <exception_object>.How It Works
- An object of the specified
<exception_class>is created. Values can be passed to the class constructor viaEXPORTINGto provide error details (e.g., the erroneous value, an ID). - Optionally, a message from message maintenance (
SE91) or another object can be linked to the exception via theMESSAGEaddition (many exception classes implement the interfaceIF_T100_MESSAGEfor this). - The normal program flow is stopped.
- The system searches upward in the call stack for a
TRY...CATCHblock that can handle this exception class (or one of its superclasses). - If a
CATCHblock is found, its code is executed. - If no matching
CATCHblock is found, this leads to a runtime error (short dump).
Exception Classes
Created in SE24 and typically inherit from:
CX_STATIC_CHECK: Errors that could potentially already be detected at development time by syntax checking (but don’t have to be). Should normally be handled.CX_DYNAMIC_CHECK: Errors that only occur at runtime but should be expected and handled by the program.CX_NO_CHECK: Severe, unexpected errors where handling is not necessarily intended (often leads to dump if not explicitly caught).
Error Handling
The caller catches these exceptions with TRY. ... CATCH cx_... INTO DATA(lo_exc). ... ENDTRY.
2. Non-class-based Exceptions (Legacy)
This is the older method, used mainly in function modules and older methods.
Context: Only meaningful in procedures (function modules, methods, FORMs) that declare such exceptions in the EXCEPTIONS addition of their interface.
Syntax
RAISE <exception_name>.How It Works
- Execution of the procedure is immediately terminated.
- The system sets the system field
sy-subrcto a value that is assigned to this<exception_name>in theEXCEPTIONSaddition of the caller (CALL FUNCTION ... EXCEPTIONS <exception_name> = value ...). - The caller must check
sy-subrcafter the call to determine if this exception occurred.
- Status: Considered obsolete for new developments, especially in the object-oriented context. Should only be used when older function modules require it.
Examples
1: Raise and Catch Class-based Exception
" Custom exception class (simplified)CLASS zcx_division_by_zero DEFINITION INHERITING FROM cx_static_check.ENDCLASS.CLASS zcx_division_by_zero IMPLEMENTATION.ENDCLASS.
START-OF-SELECTION. DATA dividend TYPE i VALUE 10. DATA divisor TYPE i VALUE 0. DATA result TYPE f. DATA lo_error TYPE REF TO zcx_division_by_zero.
TRY. IF divisor = 0. " Raise our own exception RAISE EXCEPTION TYPE zcx_division_by_zero. ELSE. result = dividend / divisor. WRITE: / 'Result:', result. ENDIF.
CATCH zcx_division_by_zero INTO lo_error. MESSAGE 'Error: Division by zero!' TYPE 'E'. " Optional: Access attributes/methods of lo_error ENDTRY.
WRITE / 'Program continues after TRY block.'.2: Class-based Exception with Message
" Assumption: Message 010 in class ZMSG: 'Material &1 is not active.'" Assumption: ZCX_MATERIAL_INACTIVE implements IF_T100_MESSAGEDATA lv_matnr TYPE matnr VALUE 'M-INACTIVE'.DATA lo_mat_error TYPE REF TO zcx_material_inactive.
TRY. " ... Check reveals that material is inactive ... RAISE EXCEPTION TYPE zcx_material_inactive MESSAGE ID 'ZMSG' TYPE 'E' NUMBER '010' WITH lv_matnr.
CATCH zcx_material_inactive INTO lo_mat_error. MESSAGE lo_mat_error->get_text( ) TYPE 'E'. " Get message from exception ENDTRY.3: Non-class-based Exception (Concept in Function Module)
FUNCTION Z_DO_SOMETHING.*"----------------------------------------------------------------------*"*"Local Interface:*" IMPORTING*" VALUE(INPUT) TYPE I*" EXPORTING*" VALUE(OUTPUT) TYPE I*" EXCEPTIONS*" INPUT_IS_ZERO " Declared exception*"---------------------------------------------------------------------- IF input = 0. RAISE input_is_zero. " raises the exception -> sy-subrc is set at caller ELSE. output = 100 / input. ENDIF.ENDFUNCTION.
" Calling program:DATA result TYPE i.CALL FUNCTION 'Z_DO_SOMETHING' EXPORTING input = 0 IMPORTING OUTPUT = result EXCEPTIONS input_is_zero = 1 " Maps exception to sy-subrc = 1 OTHERS = 2.
IF sy-subrc = 1. MESSAGE 'Input for Z_DO_SOMETHING was zero!' TYPE 'W'.ELSEIF sy-subrc = 0. WRITE: / 'Result:', result.ENDIF.Important Notes / Best Practice
- Use class-based exceptions (
RAISE EXCEPTION TYPE ...) for all new developments. - Define descriptive custom exception classes for specific error cases in your application. Derive them from
CX_STATIC_CHECKorCX_DYNAMIC_CHECK. - Implement the interface
IF_T100_MESSAGEin your exception classes to easily link them with message classes (SE91). - Pass relevant context information via the
EXPORTINGaddition to the exception class constructor. - Catch exceptions specifically with
TRY...CATCH...ENDTRYwhere they can be meaningfully handled. Let unhandleable exceptions consciously lead to a dump (especiallyCX_NO_CHECK-based ones). - Avoid
RAISE <exception_name>in new code, unless interacting with very old function modules.