The One Missing Parenthesis That Broke My ABAP Validation

The One Missing Parenthesis That Broke My ABAP Validation

SAP

Recently I spent more time than I’d like to admit debugging a validation that kept triggering in a case where it should have stayed quiet.

The code looked fine.
The fields were correct.
The syntax was clean.

But the logic was wrong and the root cause was a small thing I had not thought about in a while: how ABAP evaluates AND and OR when you don’t use parentheses.

This post is just me documenting that mistake, so I don’t repeat it - and hopefully you don’t either.


The Rule I Wanted

I had three logical conditions in my head:

  • lv_change_mode - we are in “change” mode, not “create”

  • lv_flag_missing - a flag marked when some required data is missing

  • lv_prev_failed - the previous step (say a BAPI call or check) failed

The business rule was:

Only in change mode, if either the data is missing or the previous step failed, then raise an error.

In plain words:

  • If we are changing an existing data

  • And either the required data is incomplete or the earlier step already failed

  • Then this validation should stop the user to process further


The Correct Condition

In ABAP, the condition should look like this:

IF lv_change_mode = abap_true
   AND ( lv_flag_missing = abap_true
         OR  lv_prev_failed = abap_true ).

  " Raise error

ENDIF.

Read it like this:

  • Change mode is active

  • And (required data is missing OR previous step failed)

  • Then error

This matches the business rule exactly.


The Mistake: Missing Parentheses

While refactoring, I “simplified” the condition and wrote:

IF lv_change_mode = abap_true
   AND lv_flag_missing = abap_true
   OR  lv_prev_failed = abap_true.

  " Raise error

ENDIF.

At a glance this still feels like:

change mode AND (required data missing OR prev failed)

But that’s not how ABAP reads it.

How ABAP actually evaluates it

In ABAP and basically in most programming languages, AND has higher precedence than OR.

So the runtime sees this:

( lv_change_mode = abap_true
  AND lv_flag_missing = abap_true )
OR lv_prev_failed = abap_true

The part with OR lv_prev_failed is now standing on its own, outside of the “change mode” check.

That is exactly where things went wrong.


The Scenario That Exposed the Bug

Here is the exact kind of case where my validation behaved incorrectly.

Situation

  • We are in create mode, not change
    lv_change_mode = abap_false

  • The required data is filled (Data is not missing)
    lv_flag_missing = abap_false

  • The previous step failed with an error
    lv_prev_failed = abap_true

From the business perspective:

  • We don’t even want this validation in create mode.

  • Whatever happened in the previous step, this particular check should not block the user here.

So the expected outcome is: no error.


What the correct condition does for create mode

Using the correct version:

IF lv_change_mode = abap_true
   AND ( lv_flag_missing = abap_true
         OR  lv_prev_failed = abap_true ).
  " error
ENDIF.

Evaluate it:

  • lv_change_mode = abap_trueFALSE

  • ( lv_flag_missing = abap_true OR lv_prev_failed = abap_true ) → FALSE OR TRUETRUE

Overall:

FALSE AND TRUE = FALSE

So the IF condition is not satisfied.
No error is raised.
This is exactly what we want.


What the incorrect condition does in create mode

Now look at the version without parentheses:

IF lv_change_mode = abap_true
   AND lv_flag_missing = abap_true
   OR  lv_prev_failed = abap_true.
  " error
ENDIF.

ABAP evaluates it as:

( lv_change_mode = abap_true
  AND lv_flag_missing = abap_true )
OR lv_prev_failed = abap_true

Substitute the values:

  • lv_change_mode = abap_trueFALSE

  • lv_flag_missing = abap_trueFALSE

  • lv_prev_failed = abap_trueTRUE

Now:

( FALSE AND FALSE ) OR TRUE = FALSE OR TRUE = TRUE

The condition becomes true.
The error is raised.

And that’s the bug:
The validation is now firing in create mode just because lv_prev_failed is true, even though it was supposed to run only in change mode.

One missing pair of parentheses moved lv_prev_failed outside of the “change mode” guard.


What This Has To Do With My Real Issue

In my real code, the variables were different (linked to Material data), but the pattern was the same:

  • A condition like: A AND (B OR C)

  • Was accidentally written as: A AND B OR C

  • ABAP read it as: (A AND B) OR C

  • And that last OR C condition made the IF true in cases where I did not want it to run

The code was syntactically fine.
The bug was purely logical and driven by operator precedence.


Takeaways

  1. In ABAP, AND is evaluated before OR.

  2. Any time you mix AND and OR in the same IF condition, add parentheses to make the logic explicit.

  3. When a validation fires “sometimes, but not always”, and the fields look correct, your first suspect should be the IF condition.

This was a very small mistake, but in a validation-heavy program it can completely change the business behaviour. I’m writing this down because the next time I type AND ... OR in one IF, I want a small alarm bell to ring in my head.

Tags: #sap#abap