Transitioning 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 that 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 for 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 required data is transferred
- Maintainability: Explicit field lists are more readable
- Stability: Changes to the table 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 when the entry is not found. Without TRY-CATCH, this leads to a short dump.
Typical Mistake
" WRONG: No exception handlingDATA(ls_customer) = lt_customers[ customer_id = lv_id ]." If not found: CX_SY_ITAB_LINE_NOT_FOUND -> Short dump!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
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 fields: e.g.,
persistent table,lock master - Future-proof: Prepares for new ABAP versions
- Level 2: Strictest validation (recommended for new development)
Always use it! There’s no reason to leave out 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: Built-in 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" -> Automatic 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 automatically generated from your RAP model!
9. Missing COMMIT ENTITIES for EML Operations
The Problem
EML (Entity Manipulation Language) operations like MODIFY ENTITIES require an explicit COMMIT, otherwise changes are not saved.
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 Problems Due to 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 does 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 Mistakes
| # | Mistake | 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 for Avoiding Mistakes
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 on 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
Further Resources
On abapcloud.com:
- ABAP Cloud Definition
- ABAP Cloud Cheat Sheet 2025
- RAP Basics
- CDS Views
- TRY-CATCH Statement
- Exception Classes
External Resources:
Checklist: ABAP Cloud Code Review
Before committing 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 checked: Your code is ABAP Cloud ready!
Your Most Common ABAP Cloud Mistake?
What mistake do you make most often? Is an important mistake missing from this list? Share your experiences in the comments!
Good luck with ABAP Cloud development!