10 Most Common ABAP Cloud Mistakes and How to Avoid Them (2025)

Category
Best Practices
Published
Author
Johannes

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 table
SELECT * 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 View
SELECT * FROM I_Product
INTO TABLE @DATA(lt_products).
" Or: Use Released API
DATA(lo_api) = cl_some_released_api=>get_instance( ).
DATA(lt_materials) = lo_api->get_materials( ).

How to Find Released APIs

  1. ABAP Development Tools (ADT): Use Ctrl+Shift+A -> Search for objects -> Filter “API State: Released”
  2. SAP API Business Hub: api.sap.com
  3. 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

" WRONG
SELECT * FROM I_Customer
INTO TABLE @DATA(lt_customers).

Error: SELECT * is not allowed in ABAP Cloud

Solution

Specify all fields explicitly:

" CORRECT: Explicit field list
SELECT CustomerID, CustomerName, Country
FROM I_Customer
INTO TABLE @DATA(lt_customers).
" Or: FIELDS when you need many fields
SELECT 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: Subroutines
FORM 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 method
CLASS 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.
" Usage
DATA(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 handling
DATA(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 handling
TRY.
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 found
ENDIF.

Solution 3: DEFAULT

" CORRECT: With DEFAULT value
DATA(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 Mode
managed implementation in class zbp_i_travel unique;
define behavior for ZI_Travel alias Travel
{
create;
update;
delete;
}

Solution

Add Strict Mode:

" CORRECT: With Strict Mode
managed implementation in class zbp_i_travel unique;
strict ( 2 ); // <- Important!
define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization 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 Template
DATA(lv_message) = |Customer { lv_customer_id } was activated|.
" With formatting
DATA(lv_price) = |Price: { lv_amount CURRENCY = lv_currency }|.
" With date formatting
DATA(lv_date) = |Date: { lv_timestamp TIMESTAMP = ISO }|.
" With padding
DATA(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 TABLE
DATA ls_customer TYPE ty_customer.
READ TABLE lt_customers INTO ls_customer WITH KEY customer_id = lv_id.
IF sy-subrc = 0.
" Processing
ENDIF.

Solution

Use Table Expression:

" BETTER: Table Expression with TRY-CATCH
TRY.
DATA(ls_customer) = lt_customers[ customer_id = lv_id ].
" Processing
CATCH cx_sy_itab_line_not_found.
" Not found
ENDTRY.
" Or with OPTIONAL
DATA(ls_customer) = VALUE #( lt_customers[ customer_id = lv_id ] OPTIONAL ).
IF ls_customer IS NOT INITIAL.
" Processing
ENDIF.

Advantages

  • Inline declaration: No separate DATA needed
  • 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 Dynpro
CALL 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 Definition
projection;
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 COMMIT
MODIFY 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 COMMIT
MODIFY 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 saved
ENDIF.

Best Practice

  • Always COMMIT ENTITIES after MODIFY ENTITIES
  • Check FAILED and REPORTED for 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 ABAP
SELECT 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 logic
ENDLOOP.

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 ABAP
SELECT 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

#MistakeSolution
1Using non-released APIsOnly Released CDS Views & APIs
2SELECT *Explicit field list
3FORM/PERFORMClasses with methods
4Missing exception handlingTRY-CATCH, OPTIONAL, DEFAULT
5No Strict Modestrict ( 2 ) in BDEF
6CONCATENATEString Templates |...|
7READ TABLETable Expressions lt_table[ key ]
8DynproRAP + Fiori Elements
9No COMMITCOMMIT ENTITIES after EML
10Joins in ABAPCDS 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 Cockpit

3. Use Code Templates

In ADT: Ctrl+Space for code templates

  • trycatch -> TRY-CATCH Block
  • loop -> LOOP with Table Expression
  • method -> Method definition

4. Learn from SAP Examples

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:

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 ENTITIES present?
  • 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!