Skip to Content
Author's profile photo Tobias Reiner Dolgener

Dangerous modifications II – why you should never execute a LOOP on internal tables XVBRK and XVBRP

One of the more common mistakes I came across again and again in my own work as an SAP Support Engineer is caused by modifications in user-exits. In the include RV60AFZZ (transaction SE38) several exits are available, which are executed during invoice creation. Of those, two are quite popular, which are relevant to influence the pricing functionality. Everybody does have some own requirements in the pricing area.

In FORM USEREXIT_PRICING_PREPARE_TKOMK additional custom-own fields can be filled for TKOMK, which is the header level.

And the user-exit for the item level (TKOMP) is FORM USEREXIT_PRICING_PREPARE_TKOMP.

Both are called at the start of the pricing processing in include  LV60AA58, FORM PREISFINDUNG_VORBEREITEN. First the header one, thereafter the one of the item fields at the very end:

351 PERFORM userexit_pricing_prepare_tkomk.


785  PERFORM userexit_pricing_prepare_tkomp.

Now the usual way here is to simply fill own z-fields as is suggested:

TKOMK-zzfield = xxxxzzfield2.

But what happens if you perform here a LOOP command on the internal table XVBRK? Then no errror message will be the result, as in my previous post , but instead the created invoice could be inconsistent.

In a recent case, which I investigated, two deliveries, with entirely different payers, had been created combined together in transaction VF01. In the TKOMK user-exit such a LOOP command was executed:


Now in this case an invoice split has to be performed, due to different partner data, and in XVBRK two entries exist. At the point before the LOOP command the second invoice is processed by the system and visible in the debugger as the currently processed line.

After the LOOP is executed, this line is changed, and now instead of the second invoice, the first one is the one to be processed further:


The undesired result of this manipulation: the second invoice will get the wrong partner data! It will receive the same partners as the first invoice!

So such a direct LOOP must be avoided. If data of XVBRK should be used, then a custom own table ZVBRK would have to be used, and the data moved to there. Then on the Z-table the LOOP will not cause a change in the processing line of the XVBRK.

In other cases, when the LOOP is performed on XVBRP, in the other exit USEREXIT_PRICING_PREPARE_TKOMP, then error message VF004 “Reference document & & (Error during INSERT)” could be the result, if more than one item will have to be invoiced.

Again with the LOOP command the current processing line is changed, and then the inserting of the second item will fail, because the system thinks it is the first one, which is already present in XVBRP:


So my suggestion would be to strictly refrain from such LOOP commands on internal SAP tables which are processed by the system.

Further reading:

Note 381348

Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Fred Verheul
      Fred Verheul

      Thanks for the warning Tobias!

      My suggestion though would be for SAP to make the code safe and to make sure 'we' can't even access that data in the customer specific code. I know, I'm asking too much 🙂 . One can dream though...

      Author's profile photo Tobias Reiner Dolgener
      Tobias Reiner Dolgener
      Blog Post Author

      Hi Fred,

      thanks for your feedback!

      Yes, SAP can not prevent the implementation of wrong coding in user-exits. Sure it is also a good thing, that the standard behavior can be modified, and own logic and own requirements are being fulfilled.

      Here in the described case only the direct LOOP on these internal structures, which are currently processed by the system, will have to be avoided.

      If a LOOP is required, then first the data will have to be moved to an own Z-table, and the LOOP will have to be executed there - in order not to change the currently processed line.

      Best regards,


      Author's profile photo Matthew Billingham
      Matthew Billingham

      Rather than copy to Z table, simply LOOP INTO a seperately defined work area of type XVBRP.

      This neatly demonstrates why tables with header lines (now obsolete, thankfully) are BAD.

      Author's profile photo Matthew Billingham
      Matthew Billingham

      In some exits, SAP have taken steps to prevent inadvertant modification of values. I've seen things like

      backup = original_data

      perform user_exit using original_data

      original_data = backup

      It is also possible, as others have point out below, to reduce the possibility of damaging code, by using proper encapsulation. SAP have done this in the later versions of user exits with BADIs. These SD exits though have been around for quite a while, before SAP discovered the benefits of programming properly... 😏

      Author's profile photo G Lakshmipathi
      G Lakshmipathi

      Moved from SAP ERP SD Billing to ABAP Development as this is purely technical inputs and functional team would never touch this area.

      Author's profile photo Juwin Pallipat Thomas
      Juwin Pallipat Thomas

      One of the rules that I have given to my team members is to never code directly inside any of the SAP user exits/ BADIs.

      All the logic should be within individual function modules/ methods and the user exit/ BADI should make calls to the function module/ method. This helps individual developers to work on their own code, using their own variables, using their own programming methodology and not worry about someone else modifying the code they have written. Also, if coded correctly, it is very rare that the global variables in the calling program be effected by the code inside a separate program.

      Although this method will address the issue mentioned in the blog to an extend, the correct answer to this issue is to say "Never do a LOOP/ READ, without using separate workarea/ structure".