CX_SY_NO_HANDLER¶
Raised when a
MESSAGE TYPE 'X'or unhandled exception terminates a call.
Purpose¶
CX_SY_NO_HANDLER is a wrapper exception that certain ABAP frameworks raise instead of producing a direct short dump when a TYPE 'X' message is issued inside a called unit (function module, method, or form routine). It surfaces the termination signal as a catchable class-based exception so the caller can log context before the program ends.
Inheritance chain:
CX_SY_NO_HANDLER → CX_ROOT
Not a CX_DYNAMIC_CHECK subclass
CX_SY_NO_HANDLER inherits directly from CX_ROOT, not from CX_DYNAMIC_CHECK. This means it is not automatically propagated up the call stack by the runtime — catching it only works in specific wrapper scenarios (see below). Raw MESSAGE ... TYPE 'X' statements almost always produce an immediate dump regardless of any surrounding TRY block.
When CX_SY_NO_HANDLER is actually raised¶
A plain MESSAGE e123(xy) TYPE 'X' inside a TRY block will not raise this exception — it dumps immediately. CX_SY_NO_HANDLER appears only when:
- The ABAP kernel's internal error handler decides to wrap the termination (rare, kernel-version-dependent).
- A framework (e.g. RFC server stubs, some BAdI dispatcher implementations) explicitly catches the
X-message signal and re-raises it asCX_SY_NO_HANDLER. - You use
CALL METHOD ... EXCEPTION-TABLEpatterns in some test harnesses.
Practical rule
Do not rely on catching CX_SY_NO_HANDLER as your primary safety net. Use it as a last-resort fallback alongside proper input validation that prevents TYPE 'X' messages from being issued at all.
How to attempt a catch¶
TRY.
" Call a unit that might issue MESSAGE ... TYPE 'X' via a wrapper
lo_processor->execute( ).
CATCH cx_sy_no_handler INTO DATA(lx_no_handler).
" Only reached if the framework wraps the X-message
DATA(lv_text) = lx_no_handler->get_text( ).
cl_abap_unit_assert=>fail( lv_text ). " in unit tests
" In production: log and trigger a controlled shutdown
WRITE: / 'Unhandled termination caught:', lv_text.
CATCH cx_root INTO DATA(lx_root).
" Broader fallback for any other unexpected class-based exception
WRITE: / lx_root->get_text( ).
ENDTRY.
Graceful fallback pattern¶
METHOD call_legacy_fm.
TRY.
CALL FUNCTION 'LEGACY_MODULE'
EXPORTING iv_input = iv_input.
CATCH cx_sy_no_handler INTO DATA(lx).
" Log the original message text before any further propagation
log_error( iv_msg = lx->get_text( )
iv_src = 'LEGACY_MODULE' ).
RAISE EXCEPTION TYPE cx_application_error
EXPORTING textid = cx_application_error=>unexpected_termination.
ENDTRY.
ENDMETHOD.
Do not swallow the exception silently
Catching CX_SY_NO_HANDLER and doing nothing hides a potentially critical runtime condition. Always log get_text( ) and get_longtext( ) before deciding how to proceed. In RFC or background job contexts, re-raise a meaningful application exception so the caller knows the operation failed.
See also¶
- MESSAGE_TYPE_X — short dump analysis for MESSAGE_TYPE_X terminations