CX_SY_ITAB_LINE_NOT_FOUND¶
Raised when a table expression
lt_tab[ key = 'X' ]finds no row matching the key.
Purpose¶
CX_SY_ITAB_LINE_NOT_FOUND is the exception thrown when ABAP's inline table access syntax finds no matching entry. It is a CX_DYNAMIC_CHECK — it can be caught, but the OPTIONAL addition is usually the cleaner alternative.
Inheritance chain:
CX_SY_ITAB_LINE_NOT_FOUND → CX_SY_ITAB → CX_DYNAMIC_CHECK → CX_ROOT
sy-subrc is not set by table expressions
Table expressions do not set sy-subrc. Never check sy-subrc after lt_tab[ key = 'X' ] — it retains its value from the previous statement. Use OPTIONAL or TRY/CATCH.
Reproduce¶
REPORT z_itab_line_not_found.
START-OF-SELECTION.
SELECT * FROM sflight INTO TABLE @DATA(lt_flights) UP TO 10 ROWS.
" Access with a key that has no match — raises CX_SY_ITAB_LINE_NOT_FOUND
DATA(ls_row) = lt_flights[ carrid = 'XX' connid = '9999' ].
WRITE: / ls_row-price. " never reached
How to handle¶
All examples use SAP's standard SFLIGHT table so you can run them directly in SE38 without any custom data.
REPORT z_itab_optional.
START-OF-SELECTION.
SELECT * FROM sflight INTO TABLE @DATA(lt_flights) UP TO 10 ROWS.
" Read a row that exists
DATA(ls_found) = VALUE #( lt_flights[ carrid = lt_flights[ 1 ]-carrid
connid = lt_flights[ 1 ]-connid ] OPTIONAL ).
IF ls_found IS NOT INITIAL.
WRITE: / 'Found:', ls_found-carrid, ls_found-connid, ls_found-price.
ENDIF.
" Read a row that does NOT exist — returns empty structure, no exception
DATA(ls_missing) = VALUE #( lt_flights[ carrid = 'XX' connid = '9999' ] OPTIONAL ).
IF ls_missing IS INITIAL.
WRITE: / 'Not found — handled gracefully with OPTIONAL'.
ENDIF.
REPORT z_itab_trycatch.
START-OF-SELECTION.
SELECT * FROM sflight INTO TABLE @DATA(lt_flights) UP TO 10 ROWS.
TRY.
DATA(ls_row) = lt_flights[ carrid = 'XX' connid = '9999' ].
WRITE: / ls_row-carrid, ls_row-price.
CATCH cx_sy_itab_line_not_found.
WRITE: / 'Flight XX/9999 not found — handled in CATCH'.
ENDTRY.
REPORT z_itab_lineexists.
START-OF-SELECTION.
SELECT * FROM sflight INTO TABLE @DATA(lt_flights) UP TO 10 ROWS.
DATA(lv_carrid) = lt_flights[ 1 ]-carrid.
" Check before reading — avoids the exception entirely
IF line_exists( lt_flights[ carrid = lv_carrid ] ).
DATA(ls_row) = lt_flights[ carrid = lv_carrid ].
WRITE: / 'Found:', ls_row-carrid, ls_row-price.
ELSE.
WRITE: / 'Not found'.
ENDIF.
REPORT z_itab_cond.
START-OF-SELECTION.
SELECT * FROM sflight INTO TABLE @DATA(lt_flights) UP TO 10 ROWS.
DATA(lv_carrid) = lt_flights[ 1 ]-carrid.
" Return the price if found, 0 if not — all inline
DATA(lv_price) = COND sflight-price(
WHEN line_exists( lt_flights[ carrid = lv_carrid ] )
THEN lt_flights[ carrid = lv_carrid ]-price
ELSE 0 ).
WRITE: / 'Price:', lv_price.
When to use each approach¶
| Situation | Best approach |
|---|---|
| "Not found" is normal/expected | OPTIONAL — returns empty, no exception overhead |
| "Not found" means a data error | TRY/CATCH — catch and log, makes error explicit |
| Just checking existence | LINE_EXISTS( ) — most readable |
| Read + provide default value | COND with LINE_EXISTS |
See also¶
- Clean ABAP Quick Reference — table expressions and OPTIONAL
ITAB_DUPLICATE_KEY— related internal table dump