Skip to content

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

Comments