When I am working together with local partner to resolve one issue caused by incorrect enhancement set configuration for new custom Product set type, I have realized that if the UI exception is raised and caught by framework, there would be no entry in ST22, which causes the difficulties for later trouble shooting.
When I am debugging the code how the framework handles with the exception, I found there is the possibility to let the framework call the error handler defined by ourselves being registered in table bsperrhandler.

So I think it is worthy to create a simple error handler class to persist the exception information into a new transparent table for later checking.
(1) create a class ZCL_ERROR_HANDLER with a static public method STORE_ERROR_INFO, signature as below:
METHOD store_error_info.
DATA: lv_header_text TYPE string,
l_einternal TYPE REF TO cx_bsp_einternal,
l_exception TYPE REF TO cx_root,
l_program_name TYPE syrepid,
l_include_name TYPE syrepid,
l_source_line TYPE i,
lv_log_text TYPE string,
ls_log TYPE zbsplog.
l_exception = exception.
CHECK server IS NOT INITIAL AND exception IS NOT INITIAL.
lv_header_text = exception->get_text( ).
TRY.
l_einternal ?= exception.
CATCH cx_root.
ENDTRY.
IF l_einternal IS BOUND.
CALL METHOD l_einternal->get_source_position
IMPORTING
program_name = l_program_name
include_name = l_include_name
source_line = l_source_line.
ELSE.
WHILE l_exception->previous IS BOUND.
l_exception = l_exception->previous.
ENDWHILE.
CALL METHOD l_exception->get_source_position
ENDIF.
CALL FUNCTION 'GUID_CREATE'
IMPORTING
ev_guid_16 = ls_log-uuid.
ls_log-error_date = sy-datlo.
ls_log-error_time = sy-timlo.
ls_log-error_string = |
{ lv_header_text }
Error Date:{ sy-datlo }
Error Time:{ sy-timlo }
| &&
|
Error program:{ l_program_name }
Error include:{ l_include_name }
Source code line number:{ l_source_line }
|
&& ||.
INSERT zbsplog FROM ls_log.
COMMIT WORK AND WAIT.
ENDMETHOD.
data: lt_table type STANDARD TABLE OF zbsplog,
lv_error TYPE zbsplog-error_string.
FIELD-SYMBOLS: TYPE zbsplog.
START-OF-SELECTION.
SELECT * INTO TABLE lt_table FROM zbsplog.
LOOP AT lt_table ASSIGNING .
WRITE:/ 'guid: ', -uuid,'date: ', -error_date, -error_time.
lv_error = -error_string.
HIDE lv_error.
ENDLOOP.
AT LINE-SELECTION.
cl_demo_output=>display_html( lv_error ).
execute the report and double click one line item, the detail information would be displayed via the handy class cl_demo_output.
With the include name and source code line number available, you could implement further handling like automatically navigation to the source code in ABAP editor by calling function module RS_TOOL_ACCESS with include name and source code number passed in.