ABAP Core Part 8: Messages and User-Friendly Error Handling
Use messages correctly: message classes and numbers, message types (S, I, W, E, A, X) and their behavior in different contexts, placeholders, MESSAGE … INTO for logging, and collecting messages instead of stopping at the first error.
Explanation
📌 KEY POINTS
✅ Messages live in message classes (SE91 / ADT) with a number and up to 4 placeholders (&1–&4).
✅ Type decides behavior: S (status), I (info popup), W (warning), E (error), A (abort), X (dump).
✅ The same type behaves differently by context (selection screen, list, dialog, background, RAP).
💡 MESSAGE … INTO lv_text creates the text without showing it — ideal for logs and return tables.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 5 showed an error message on the selection screen. This part explains messages properly.
━━━━━━━━━━━━━━━━━━━━
▶ 1. MESSAGE CLASSES
Create a message class (e.g. ZFLIGHT) with numbered texts:
001 Airline &1 does not exist
002 No authorization for airline &1
003 Flight &1 &2 on &3 is fully booked
Texts are translatable — never hard-code user messages in code.
━━━━━━━━━━━━━━━━━━━━
▶ 2. SENDING A MESSAGE
MESSAGE e001(zflight) WITH p_carr.
or with a structured form: MESSAGE ID 'ZFLIGHT' TYPE 'E' NUMBER '001' WITH p_carr.
━━━━━━━━━━━━━━━━━━━━
▶ 3. MESSAGE TYPES AND BEHAVIOR (CLASSIC REPORTS)
- S — status bar message; processing continues.
- I — information popup; processing continues after confirmation.
- W — warning; on screens the user can confirm and continue.
- E — error; on the selection screen/dynpro the user must correct input; in START-OF-SELECTION it ends the processing and shows the message.
- A — termination (abort) of the transaction.
- X — short dump (only for impossible situations).
⚠️ WATCH OUT: in background jobs, function modules and RFC, E/A messages behave differently (e.g. cancel the job or become exceptions) — do not use MESSAGE E deep inside reusable code.
━━━━━━━━━━━━━━━━━━━━
▶ 4. MESSAGES IN REUSABLE CODE
In classes, function modules and services, don't "show" messages. Instead:
- raise exceptions (Part 9) or
- return messages in a table (BAPIRET2 style) or
- in RAP, fill REPORTED.
Create the text with MESSAGE … INTO lv_dummy — sy-msgid, sy-msgno and sy-msgv1–4 are filled, so you can store it.
━━━━━━━━━━━━━━━━━━━━
▶ 5. COLLECTING MESSAGES
Show all problems at once instead of stopping at the first: collect into a table and display (e.g. application log via BAL function modules or classes, or a simple list/ALV).
━━━━━━━━━━━━━━━━━━━━
▶ 6. APPLICATION LOG
For background processing and interfaces, write messages to the application log (SLG1) so support can analyze them later.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Create message class ZFLIGHT with messages 001–003.
- Use them in the report as in the code example.
- Try types S, I, W, E and observe the behavior.
- Collect messages with MESSAGE … INTO and display them together.
✅ CHECKPOINT: your programs communicate errors clearly and support-friendly.
Code example
REPORT zabap_core_messages MESSAGE-ID zflight.* Message class ZFLIGHT (SE91):* 001 Airline &1 does not exist* 002 No authorization for airline &1* 003 Flight &1 &2 on &3 is fully booked* 004 &1 flights checked, &2 fully booked PARAMETERS p_carr TYPE s_carr_id DEFAULT 'LH'. DATA: lt_flights TYPE STANDARD TABLE OF sflight, ls_f TYPE sflight, lt_messages TYPE STANDARD TABLE OF bapiret2, ls_message TYPE bapiret2, lv_dummy TYPE string, lv_full TYPE i, lv_checked TYPE i, lv_carrid TYPE s_carr_id. AT SELECTION-SCREEN. SELECT SINGLE carrid FROM scarr INTO lv_carrid WHERE carrid = p_carr. IF sy-subrc <> 0. MESSAGE e001 WITH p_carr. " E on selection screen: user corrects input ENDIF. START-OF-SELECTION. SELECT * FROM sflight INTO TABLE lt_flights UP TO 50 ROWS WHERE carrid = p_carr. * ===== Collect messages instead of stopping at the first ===== LOOP AT lt_flights INTO ls_f WHERE seatsocc >= seatsmax. lv_full = lv_full + 1. MESSAGE w003 WITH ls_f-carrid ls_f-connid ls_f-fldate INTO lv_dummy. " text only CLEAR ls_message. ls_message-type = sy-msgty. ls_message-id = sy-msgid. ls_message-number = sy-msgno. ls_message-message_v1 = sy-msgv1. ls_message-message_v2 = sy-msgv2. ls_message-message_v3 = sy-msgv3. ls_message-message = lv_dummy. APPEND ls_message TO lt_messages. ENDLOOP. * ===== Show collected messages ===== LOOP AT lt_messages INTO ls_message. WRITE: / ls_message-type, ls_message-message. ENDLOOP. * ===== Status message at the end: processing continues ===== DESCRIBE TABLE lt_flights LINES lv_checked. MESSAGE s004 WITH lv_checked lv_full. * In function modules / classes: do NOT show messages -* return BAPIRET2 tables or raise exceptions.* 💡 Modern syntax (7.40+): APPEND VALUE #( type = sy-msgty id = sy-msgid ... ) TO lt_messages.Real project scenario
A mass upload program stopped at the first invalid line with MESSAGE E, so users fixed one error, restarted, hit the next error, and needed a dozen runs for one file. In background mode the job simply cancelled with little context.
The redesign validated all lines first, collected messages with MESSAGE … INTO into a BAPIRET2 table and the application log, and showed a summary. Users now fixed all errors in one pass, and support could analyze background runs in SLG1.
Common mistakes
- Hard-coded message texts instead of message classes.
- MESSAGE E inside reusable classes or function modules.
- Stopping at the first error in mass processing.
- Using type X or A for normal business errors.
- No application log for background processing.
Best practices
- Use message classes with placeholders for all user texts.
- Choose the type by desired behavior and context.
- In reusable code, raise exceptions or return messages.
- Collect messages for mass processing.
- Log background and interface messages in the application log.
Interview angle
Questions: "Explain message types S, I, W, E, A, X", "Why not use MESSAGE E in a function module?", "What does MESSAGE … INTO do?"
Strong answer: S status, I info popup, W warning, E error (correct input on screens, ends processing in lists), A abort, X dump; behavior depends on context, and in reusable/background code E/A can cancel callers or jobs, so return messages or raise exceptions; MESSAGE … INTO builds the text and fills sy-msg fields without displaying — for logs and BAPIRET2 tables.
Practice this lesson
Quick check
1. Why should MESSAGE with type E be avoided deep inside a reusable class method?
2. What does MESSAGE e003(zflight) INTO lv_text WITH lv_carr do?
3. MESSAGE type 'X' does what?
Interview questions
1. A sales upload stops at the first invalid material, forcing users to rerun many times. How would you redesign error handling?
Answer it in your own words first, then compare.
2. You're designing the exception handling and logging strategy for a strategic, long-lived custom framework (used by 200+ Z-programs across the enterprise) that will be maintained by multiple teams over many years. What principles would guide your design to keep it maintainable and diagnosable long-term?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- ABAP Core Part 1: Your First ABAP Program and the Development Tools
- ABAP Core Part 10: Clean ABAP Basics for Maintainable Code
- ABAP Core Part 2: DATA, TYPES, CONSTANTS, Work Areas and Internal Tables
- ABAP Core Part 3: Data Types and Literals
- ABAP Core Part 4: Control Flow and Building Output Texts
- ABAP Core Part 5: Selection Screens — PARAMETERS, SELECT-OPTIONS and Validation
- ABAP Core Part 6: System Fields — sy-subrc, sy-tabix, sy-datum and More
- ABAP Core Part 7: Operators, Calculations and Type Conversion