The transition from Classic ABAP to ABAP Cloud brings many challenges. New rules, restricted APIs, and modern syntax can trip up even experienced ABAP developers.
In this article, we show the 10 most common mistakes ABAP Cloud developers make - with practical solutions and code examples, so you can avoid these pitfalls from the start.
1. ❌ Using Non-Released APIs and Objects
The Problem
In ABAP Cloud, you may only use Released APIs. Accessing internal SAP tables, function modules, or classes without released status leads to syntax errors.
Typical Mistake
" ❌ WRONG: Direct access to SAP tableSELECT * FROM mara INTO TABLE @DATA(lt_materials).Error: MARA is not released for ABAP Cloud
✅ Solution
Use CDS Views with Released Status or Released APIs:
" ✅ CORRECT: Use Released CDS ViewSELECT * FROM I_Product INTO TABLE @DATA(lt_products).
" Or: Use Released APIDATA(lo_api) = cl_some_released_api=>get_instance( ).DATA(lt_materials) = lo_api->get_materials( ).💡 How to Find Released APIs
- ABAP Development Tools (ADT): Use
Ctrl+Shift+A→ Search objects → Filter “API State: Released” - SAP API Business Hub: api.sap.com
- Released Objects Browser: Transaction
SOTS_REGISTRY(in compatible systems)
Tip: In ADT, released objects show a green checkmark in the object list.
2. ❌ SELECT * Instead of Explicit Field List
The Problem
SELECT * is not allowed in ABAP Cloud. You must always explicitly specify which fields you want to read.
Typical Mistake
" ❌ WRONGSELECT * FROM I_Customer INTO TABLE @DATA(lt_customers).Error: SELECT * is not allowed in ABAP Cloud
✅ Solution
Specify all fields explicitly:
" ✅ CORRECT: Explicit field listSELECT CustomerID, CustomerName, Country FROM I_Customer INTO TABLE @DATA(lt_customers).
" Or: FIELDS when you need many fieldsSELECT CustomerID, CustomerName, Country, City, PostalCode FROM I_Customer INTO TABLE @DATA(lt_customers).💡 Why?
- Performance: Only needed data is transferred
- Maintainability: Explicit field lists are more readable
- Stability: Table changes won’t break your code
3. ❌ Using FORM/PERFORM Instead of Methods
The Problem
Subroutines with FORM and PERFORM are forbidden in ABAP Cloud. You must work object-oriented with classes and methods.
Typical Mistake
" ❌ WRONG: SubroutinesFORM calculate_total USING pv_amount TYPE p CHANGING pv_total TYPE p. pv_total = pv_amount * '1.19'.ENDFORM.
PERFORM calculate_total USING lv_amount CHANGING lv_total.Error: FORM/PERFORM is not allowed in ABAP Cloud
✅ Solution
Use classes with methods:
" ✅ CORRECT: Class with methodCLASS lcl_calculator DEFINITION. PUBLIC SECTION. CLASS-METHODS calculate_total IMPORTING iv_amount TYPE p RETURNING VALUE(rv_total) TYPE p.ENDCLASS.
CLASS lcl_calculator IMPLEMENTATION. METHOD calculate_total. rv_total = iv_amount * '1.19'. ENDMETHOD.ENDCLASS.
" UsageDATA(lv_total) = lcl_calculator=>calculate_total( lv_amount ).💡 Best Practice
- Use local classes (
lcl_) for internal logic - Use global classes (
zcl_,ycl_) for reusable components - Use static methods for utility functions
4. ❌ Missing Exception Handling for Table Expressions
The Problem
Table expressions like lt_table[ key = value ] throw an exception if the entry is not found. Without TRY-CATCH, this leads to a shortdump.
Typical Mistake
" ❌ WRONG: No exception handlingDATA(ls_customer) = lt_customers[ customer_id = lv_id ]." If not found: CX_SY_ITAB_LINE_NOT_FOUND → Shortdump!✅ Solution 1: TRY-CATCH
" ✅ CORRECT: With exception handlingTRY. DATA(ls_customer) = lt_customers[ customer_id = lv_id ]. " Processing CATCH cx_sy_itab_line_not_found. " Error handling ls_customer = VALUE #( customer_id = 0 name = 'Unknown' ).ENDTRY.✅ Solution 2: OPTIONAL
" ✅ CORRECT: With OPTIONAL (no exception)DATA(ls_customer) = VALUE #( lt_customers[ customer_id = lv_id ] OPTIONAL ).
IF ls_customer IS INITIAL. " Not foundENDIF.✅ Solution 3: DEFAULT
" ✅ CORRECT: With DEFAULT valueDATA(ls_customer) = VALUE #( lt_customers[ customer_id = lv_id ] DEFAULT VALUE #( customer_id = 0 name = 'Not found' ) ).💡 When to Use What?
- TRY-CATCH: When not finding is an error case
- OPTIONAL: When not finding is normal (then check with
IS INITIAL) - DEFAULT: When you need a default value
5. ❌ Missing Strict Mode in RAP Behavior Definitions
The Problem
The Strict Mode (strict ( 2 )) in RAP ensures best-practice validation. Without it, errors are only detected at runtime.
Typical Mistake
" ❌ WRONG: No Strict Modemanaged implementation in class zbp_i_travel unique;
define behavior for ZI_Travel alias Travel{ create; update; delete;}✅ Solution
Add Strict Mode:
" ✅ CORRECT: With Strict Modemanaged implementation in class zbp_i_travel unique;strict ( 2 ); // <- Important!
define behavior for ZI_Travel alias Travelpersistent table ztravellock masterauthorization master ( instance ){ create; update; delete;}💡 What Does Strict Mode Do?
- Syntax checks: Enforces best practices
- Required statements: e.g.,
persistent table,lock master - Future-proof: Prepares for new ABAP versions
- Level 2: Strictest validation (recommended for new developments)
Always use it! There’s no reason to omit Strict Mode.
6. ❌ CONCATENATE Instead of String Templates
The Problem
CONCATENATE is obsolete. String templates are more modern, readable, and powerful.
Typical Mistake
" ❌ WRONG: CONCATENATE (obsolete)DATA lv_message TYPE string.CONCATENATE 'Customer' lv_customer_id 'was activated' INTO lv_message SEPARATED BY space.✅ Solution
Use String Templates:
" ✅ CORRECT: String TemplateDATA(lv_message) = |Customer { lv_customer_id } was activated|.
" With formattingDATA(lv_price) = |Price: { lv_amount CURRENCY = lv_currency }|.
" With date formattingDATA(lv_date) = |Date: { lv_timestamp TIMESTAMP = ISO }|.
" With paddingDATA(lv_padded) = |{ lv_id WIDTH = 10 ALIGN = RIGHT PAD = '0' }|." Result: "0000000042"💡 Advantages of String Templates
- Readable: Clearly structured
- Powerful: Integrated formatting
- Modern: Best practice in ABAP Cloud
- Shorter: Less code
7. ❌ READ TABLE Instead of Table Expressions
The Problem
READ TABLE is not forbidden, but obsolete. Table expressions are shorter and more modern.
Typical Mistake
" ❌ NOT IDEAL: READ TABLEDATA ls_customer TYPE ty_customer.READ TABLE lt_customers INTO ls_customer WITH KEY customer_id = lv_id.IF sy-subrc = 0. " ProcessingENDIF.✅ Solution
Use Table Expression:
" ✅ BETTER: Table Expression with TRY-CATCHTRY. DATA(ls_customer) = lt_customers[ customer_id = lv_id ]. " Processing CATCH cx_sy_itab_line_not_found. " Not foundENDTRY.
" Or with OPTIONALDATA(ls_customer) = VALUE #( lt_customers[ customer_id = lv_id ] OPTIONAL ).IF ls_customer IS NOT INITIAL. " ProcessingENDIF.💡 Advantages
- Inline declaration: No separate
DATAneeded - Shorter: One line instead of three
- Modern: Best practice in ABAP Cloud
Note: READ TABLE still works, but table expressions are the future.
8. ❌ Dynpro Development Instead of SAP Fiori
The Problem
Dynpro (classic SAP GUI) is no longer possible in ABAP Cloud. The UI must be built with SAP Fiori.
Typical Mistake
" ❌ WRONG: Using DynproCALL SCREEN 100.
MODULE status_0100 OUTPUT. SET PF-STATUS 'MAIN'. SET TITLEBAR 'TITLE'.ENDMODULE.Error: Dynpro is not available in ABAP Cloud
✅ Solution
Use RAP + SAP Fiori Elements:
" ✅ CORRECT: RAP Business Object with Service Binding
" 1. CDS View (Data Model)@EndUserText.label: 'Customer View'define root view entity ZC_Customer as projection on ZI_Customer{ key CustomerId, CustomerName, Email, Status}
" 2. Behavior Definitionprojection;strict ( 2 );
define behavior for ZC_Customer{ use create; use update; use delete;}
" 3. Service Definition@EndUserText.label: 'Customer Service'define service ZUI_CUSTOMER_O4 { expose ZC_Customer as Customer;}
" 4. Service Binding (OData V4 - UI)" Type: OData V4 - UI" → Automatically Fiori Elements App!💡 Advantages of Fiori
- Modern: Responsive, touch-optimized
- Cloud-ready: Runs everywhere (browser, tablet, mobile)
- Low maintenance: Fiori Elements generates UI automatically
- Consistent: Unified SAP experience
Tip: Use SAP Fiori Elements - the UI is generated automatically from your RAP model!
9. ❌ Missing COMMIT ENTITIES in EML Operations
The Problem
EML (Entity Manipulation Language) operations like MODIFY ENTITIES require an explicit COMMIT, otherwise changes are not persisted.
Typical Mistake
" ❌ WRONG: No COMMITMODIFY ENTITIES OF zi_travel ENTITY Travel UPDATE FIELDS ( Status ) WITH VALUE #( ( TravelId = lv_id Status = 'A' ) ).
" Changes are lost! ❌✅ Solution
Use COMMIT ENTITIES:
" ✅ CORRECT: With COMMITMODIFY ENTITIES OF zi_travel ENTITY Travel UPDATE FIELDS ( Status ) WITH VALUE #( ( TravelId = lv_id Status = 'A' ) ) FAILED DATA(failed) REPORTED DATA(reported).
" IMPORTANT: Don't forget COMMIT!COMMIT ENTITIES RESPONSE OF zi_travel FAILED DATA(commit_failed) REPORTED DATA(commit_reported).
IF commit_failed IS INITIAL. " Successfully savedENDIF.💡 Best Practice
- Always COMMIT ENTITIES after
MODIFY ENTITIES - Check
FAILEDandREPORTEDfor errors - In Behavior Implementations: No COMMIT (framework handles it)
- Only use COMMIT in external code (e.g., reports, classes)
10. ❌ Performance Issues from Missing CDS Associations
The Problem
Joins in ABAP code instead of CDS Associations leads to poor performance and unreadable code.
Typical Mistake
" ❌ WRONG: Joins in ABAPSELECT c~customer_id, c~name, o~order_id, o~order_date FROM ztab_customers AS c INNER JOIN ztab_orders AS o ON c~customer_id = o~customer_id WHERE c~status = 'ACTIVE' INTO TABLE @DATA(lt_result).
" Then manually aggregate, filter, etc.LOOP AT lt_result INTO DATA(ls_result). " Complex logicENDLOOP.✅ Solution
Use CDS Views with Associations:
/* ✅ CORRECT: CDS View with Association */@AbapCatalog.sqlViewName: 'ZVCUSTOMER'@EndUserText.label: 'Customer with Orders'
define view Z_Customer as select from ztab_customers as c association [0..*] to ztab_orders as _Orders on c.customer_id = _Orders.customer_id{ key c.customer_id as CustomerId, c.name as CustomerName, c.status as Status,
/* Expose association */ _Orders}" Usage in ABAPSELECT FROM Z_Customer FIELDS CustomerId, CustomerName WHERE Status = 'ACTIVE' INTO TABLE @DATA(lt_customers).
" Load orders when needed (Lazy Loading)SELECT FROM Z_Customer FIELDS CustomerId, \_Orders-OrderId, \_Orders-OrderDate WHERE Status = 'ACTIVE' INTO TABLE @DATA(lt_customer_orders).💡 Advantages
- Performance: DB performs joins (not ABAP)
- Reusable: Association can be used in all views
- Lazy Loading: Only load orders when needed
- Readable: Clear data modeling
Rule of thumb: Joins belong in CDS Views, not in ABAP code!
🎯 Summary: The 10 Most Common ABAP Cloud Errors
| # | Error | Solution |
|---|---|---|
| 1 | Using non-released APIs | Only Released CDS Views & APIs |
| 2 | SELECT * | Explicit field list |
| 3 | FORM/PERFORM | Classes with methods |
| 4 | Missing exception handling | TRY-CATCH, OPTIONAL, DEFAULT |
| 5 | No Strict Mode | strict ( 2 ) in BDEF |
| 6 | CONCATENATE | String Templates |...| |
| 7 | READ TABLE | Table Expressions lt_table[ key ] |
| 8 | Dynpro | RAP + Fiori Elements |
| 9 | No COMMIT | COMMIT ENTITIES after EML |
| 10 | Joins in ABAP | CDS Associations |
🛠️ Practical Tips to Avoid Errors
1. Use ABAP Development Tools (ADT)
- Eclipse with ADT detects ABAP Cloud errors immediately
- Syntax highlighting for Released/Non-Released objects
- Quick fixes for many errors
2. Enable ATC Checks
ABAP Test Cockpit checks code for ABAP Cloud conformity:
" In ADT: Right-click object → Run As → ABAP Test Cockpit3. Use Code Templates
In ADT: Ctrl+Space for code templates
trycatch→ TRY-CATCH blockloop→ LOOP with table expressionmethod→ Method definition
4. Learn from SAP Examples
- SAP Developers Tutorials: developers.sap.com
- GitHub SAP-Samples: github.com/SAP-samples
- SAP Community: community.sap.com
5. Use Migration Tools
For migrations from Classic ABAP:
- Custom Code Migration App (Fiori App in system)
- ABAP Test Cockpit with Cloud checks
- SAP BTP ABAP Environment Migration Tool
📚 Additional Resources
On abapcloud.com:
- ABAP Cloud Definition
- ABAP Cloud Cheat Sheet 2025
- RAP Fundamentals
- CDS Views
- TRY-CATCH Statement
- Exception Classes
External Resources:
✅ Checklist: ABAP Cloud Code Review
Before you commit code, check:
- Only Released APIs used?
- No
SELECT *statements? - No
FORM/PERFORM? - Table expressions with exception handling?
- Strict Mode enabled in BDEFs?
- String templates instead of
CONCATENATE? - Modern syntax (VALUE, CORRESPONDING, etc.)?
- For EML:
COMMIT ENTITIESpresent? - Fiori instead of Dynpro?
- CDS Associations instead of joins in ABAP?
If all points are ✅: Your code is ABAP Cloud ready! 🎉
💬 Your Most Common ABAP Cloud Error?
Which error do you make most frequently? Is an important error missing from this list? Share your experiences in the comments!
Good luck with ABAP Cloud development! 🚀