SYNTAX_ERROR¶
Dynamically generated ABAP code contained a syntax error detected at runtime.
This is a runtime syntax error — distinct from the compile-time errors caught by SE38's syntax check. The error occurs when ABAP generates or compiles code dynamically and the generated source contains invalid syntax.
Symptom¶
ST22 shows:
Runtime Errors SYNTAX_ERROR
Exception CX_SY_SYNTAX_ERROR (in newer kernels)
Short text Syntax error in dynamically generated program.
The dump includes a "Generated source" or "Dynamic program" section showing the code that failed to compile.
Cause¶
Dynamic ABAP constructs that generate code at runtime:
| Statement | What it generates |
|---|---|
GENERATE SUBROUTINE POOL |
Builds a temporary program from string lines |
INSERT REPORT |
Writes a new program source to the repository |
CREATE DATA ... TYPE (lv_type_name) |
Type resolved at runtime |
Common triggers:
- A string built to pass to
GENERATE SUBROUTINE POOLcontains a typo, missing period, or unclosed string literal. - A dynamic type name (
TYPE (lv_type)) contains a name that doesn't exist in the DDIC.
Reproduce¶
The reproduce example uses GENERATE SUBROUTINE POOL with intentionally broken source code. The error message appears — no actual dump is triggered if you check sy-subrc:
DATA lt_source TYPE STANDARD TABLE OF string.
DATA lv_prog TYPE string.
APPEND 'REPORT ztemp.' TO lt_source.
APPEND 'FORM test.' TO lt_source.
APPEND ' DATA lv_x TYPE' TO lt_source. " missing type name — syntax error
APPEND 'ENDFORM.' TO lt_source.
GENERATE SUBROUTINE POOL lt_source NAME lv_prog
MESSAGE DATA(lv_msg)
SHORTDUMP-ID DATA(lv_dump_id).
IF sy-subrc <> 0.
" lv_msg contains the description of the syntax error
MESSAGE lv_msg TYPE 'E'. " e.g. "Field '.' is unknown."
ENDIF.
The actual dump fires only if you skip the sy-subrc check and call PERFORM ... IN PROGRAM (lv_prog) when generation failed — because the program doesn't exist.
Fix¶
This is the same example as reproduce, but now we fix the source code so generation succeeds:
DATA lt_source TYPE STANDARD TABLE OF string.
DATA lv_prog TYPE string.
" Fixed source — complete TYPE declaration
APPEND 'REPORT ztemp.' TO lt_source.
APPEND 'FORM test.' TO lt_source.
APPEND ' DATA lv_x TYPE i.' TO lt_source. " now valid
APPEND 'ENDFORM.' TO lt_source.
GENERATE SUBROUTINE POOL lt_source NAME lv_prog
MESSAGE DATA(lv_msg)
SHORTDUMP-ID DATA(lv_dump_id).
IF sy-subrc <> 0.
" Generation failed — log the message, do NOT call PERFORM
MESSAGE |Dynamic program syntax error: { lv_msg }| TYPE 'E'.
RETURN.
ENDIF.
" Only call PERFORM if generation succeeded (sy-subrc = 0)
PERFORM test IN PROGRAM (lv_prog).
If your reproduce error comes from an invalid dynamic type name:
REPORT z_syntax_error_fix2.
START-OF-SELECTION.
DATA: lv_type_name TYPE string VALUE 'BAPI_RETURN',
lo_data TYPE REF TO data,
lo_type TYPE REF TO cl_abap_typedescr.
" describe_by_name raises classical exception TYPE_NOT_FOUND (not OO).
" Use CALL METHOD with EXCEPTIONS — do NOT use TRY/CATCH here.
CALL METHOD cl_abap_typedescr=>describe_by_name
EXPORTING
p_name = lv_type_name
RECEIVING
p_descr_ref = lo_type
EXCEPTIONS
type_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE |Type { lv_type_name } does not exist in DDIC| TYPE 'E'.
RETURN.
ENDIF.
" Type confirmed — safe to use in CREATE DATA
CREATE DATA lo_data TYPE (lv_type_name).
WRITE: / 'Type exists:', lo_type->get_relative_name( ).
Dynamic code generation is a last resort
GENERATE SUBROUTINE POOL is powerful but fragile. Prefer static code, polymorphism, or configuration tables over dynamically assembled source code. Every string you assemble is a potential syntax error.
Prevention¶
- Always check
sy-subrcafterGENERATE SUBROUTINE POOLbefore calling the generated program. - Log
lv_msgwhen generation fails — it contains the exact syntax error location. - Validate all dynamic type names with
CL_ABAP_TYPEDESCR=>DESCRIBE_BY_NAMEbefore use.
See also¶
LOAD_PROGRAM_NOT_FOUND— related dynamic program dump- Transaction ST22 — ABAP runtime error analysis (includes generated source in dump)