Skip to Content


The new ABAP-Objects Workflow has taken over the existing concept of temporary and application exception, as it was used with BOR-based Workflows. It has been replaced by using a set of predefined exceptions within the method’s implementation.

The most commonly used exceptions are the following

Exception class Type Description
CX_BO_ERROR Error Application error occurred
CX_BO_TEMPORARY Temporary Temporary, recoverable error occured
CX_BO_ACTION_CANCELLED Temporary User has cancelled the processing

You may also lookup for more exception, using the class builder and lookup the class hierarchy of CX_BO_TEMPORARY and CX_BO_APPLICATION, that are the two top-classes for the ABAP-OO Workflow Exceptions.

To use one of the given classes, you can just defined them in the “Exception” definition of the method.

01 Method exceptions.png

The simplest way to make use of the feature that you’ve just created, is like this


With the BOR-based implementation, you had to define each exception with reference to a message-ID. This message-ID, including the four variables sy-msgv1,… were then displayed in the workflow log, and under the “Message” button of the workitem, which is a very nice feature, as you can provide more detailed information othen than just saying “There was some kind of error, and you could recover it, because it’s possibly temporary”.

02 BOR Exception definition.png

And by raising the exception, you could pass more information to the workflow log.

exit_return 9001 ‘WACHF’.   “User &1 is currently locking table XYZ

With the ABAP-OO implementation, this has become a bit more complicated, but once you’re through with it, it becomes fairly easy.

I do not repeat the common basis to define the outcomes in the step definition, how to create an ABAP-OO-Workflow class and so forth. Please read through the SCN, documentation or visit BIT611 for more information on that general topic.

Using custom text for OO-Workflow Exceptions

You can use the predefined classes and populate them with your own “text element” to have some more information displayed to the end user or the administration. The first – simplest – approach is, to create a new textID in the repository and use that, when raising the exception.

Create a new “concept” with transaction SOTR_EDIT.

Maintenance screen of SOTR_EDIT Call menu option Concept – Create
03 SOTR_EDIT1.png 04 SOTR_EDIT2.png

Then fill in the screen for a new concept, which becomes the TEXTID later on. The field “Object Type” needs to be filled, but it’s pretty much useless here.

Please read through the documentation of the transaction to find out, how to translate the object into other languages, create a transport request, and so on.

05 SOTR_EDIT3 Create new concept.png

After you’ve created the new concept, you’ll get a new GUID, which I would suggest to save it into a class constant.

06 SOTR_EDIT concept created.png

To make use of this custom text within the exception handling of the workflow, you can simply use the following ABAP:

RAISE EXCEPTION TYPE cx_bo_temporary EXPORTING textID = ‘0050568015291ED2ABB3C86EAD8513B4’.

That’s it, already!

This will now look like this in the workflow log:

07 Log 1.png

08 Log2.png

However, sometimes, that not just enough. … and the story continues …

Using custom texts with variables

To make text replacements for the text of the exception class, there’re two general approaches possible: Using a TEXTID based exception or a MESSAGE based exception. In the following section I will outline how to implement this with a TEXTID.

Create a new subclass of the exception type, you need, e.g. a temporary exception. So create a new class ZCX_TEMPORARY_WITH_TEXT, inheritingfrom CX_BO_TEMPORARY. Please be aware, that the exception class name must begin with ZCX…, YCX… or /<namespace>/CX…

After activation of the class, a new attribute is generated, which will be the default textID when the exception class is instantiated:

With some newer ECC-Release a new button appears here “Message Text” appears here, where you can assign a MESSAGE ID, and furthermore, thanks to the note from Mike (see comment section below), if you edit the long text here, you do not need to go to the SOTR_EDIT transaction.

Create new member attributes for that class, as you like. In this example: USERNAME. It must be the same naming as you’re using between the & and & of the text element.

10 New attribute.png

The usage is now a bit different. So first of all, you need to list the exception in the method signature, of course:

11 Exception method with text.png

And you cannot use the shortcut ABAP statement anymore, because you will need the following three steps:

– Instance a new exception class

– Assign the text elements before raising the exception

– Raise the exception object instance

“Special lock exception with text replacement on-the-fly

DATA: lx_temporary_locked                TYPE REF TO ZCX_TEMPORARY_WITH_TEXT.

        CREATE OBJECT lx_temporary_locked.

        “All text elements embraced by & will be replaced by instance attributes

lx_temporary_locked->username = ‘WACHF’.    “As an example

       RAISE EXCEPTION lx_temporary_locked.   “Object is temporary locked by user WACHF

or use this shortcut, as for each attribute an importing parameter will be generated for the CONSTRUCTOR, that can’t be changed otherwise. If you need to fill more tricky values, you need to use the proposed solution above.


And in the workflow log, it appears now like this:

12 Object text with replace.png

And this is really an improvement, when comparing it with the default text:

13 standard message.png

It’s some work, but it’s very nice to use, when you got there.

Variant 2 – Using exception with message classes

Thanks to the comment of Jocelyn, I’ve added the part to populate a message-ID to an exception and raise that. However, I didn’t find any substance need to modify/enhance the exception’s constructor. It’s working without any coding (changes).

The existing class CX_BO_TEMPORARY is not an exception-class “with message class”, so you can’t use it directly, but you have to subtype it. So please subtype a new class, e.g. ZCX_TEMP_EXCEPTION_WITH_MESSAGE from the super exception class CX_BO_TEMPORARY.

14 Create CX with message.png

Check the box “With Message Class” now.

After that, activate the new class. You don’t need to make any changes in the subtyped exception class.

If you found an exception list that already contains the superior exception class, i.e. CX_BO_TEMPORARY is already defined, you don’t need to add the new subtype to the exception list. It will be cast to the superior class.

There’s no additional coding except to correctly raise that message. In my example, I chose to set the message WF 015 “Cancelled by user”:

DATA: ls_message              TYPE SCX_T100KEY,

      lv_message_text(50)     TYPE C.   “Dummy message holder

MESSAGE I015(WF) INTO lv_message_text.     “For where-used list and SY variables

ls_message-msgid = sy-msgid.

ls_message-msgno = sy-msgno.

ls_message-attr1 = sy-msgv1.

ls_message-attr2 = sy-msgv2.

ls_message-attr3 = sy-msgv3.

ls_message-attr4 = sy-msgv4.

RAISE EXCEPTION TYPE zcx_temporary_with_message EXPORTING textid = ls_message.

After that, you can find a temporary exception in your workflow log with  the detailed message!

15 Message in log.png

Any helpful comments are very welcome.

Please “rate” or “like” if you find this information useful.

Take care.

    Florin Wach


    SAP Business Workflow Senior-Expert

Update 1: Changed and reworked section  Using custom texts with variables

Update 2: Changed a paragraph at the end, explaining that an existing CX_BO_TEMPORARY exception signature doesn’t need to be changed.

Update 3: Included comment from Mike regarding the message texting.

To report this post you need to login first.


You must be Logged on to comment or reply to a post.

  1. Jocelyn Dart

    Hi Florin, Very nice clean example. 

    BTW atsome sites we’ve taken this a step further and played around with the constructor coding of the custom exception class. This is quite useful e.g. if you want to pass across standard message formats (with message number, class, variables 1-4) and then extract the T100 message and replace variables in the format before adding it to the workflow log.   Very similar to what you have done… just needs a little extra coding in the constructor method and that’s all.



  2. andrew curtis


    Nice.  Behind the Exception Class Text is a Long Text, that you can also add Class Attributes into.  I thought this would be a great place to put a table of messages returned from the Task thats just Raised the Exception.  My problem is, that although in the Wf Log I can see the Text in a popup as you presented here, what I could not see was the Long text.  Did you find a way of presenting the Long Text?

    1. Florin Wach Post author

      Hello Andrew!

      That’s an interesting requirement, and I’ve an idea, and also posted another blog to address a different approach.

      I would suggest to go through the E-Messages returned by the BAPI, pick up the very first one and create an Exception-Object based on that Message-ID. So the BAPI message becomes itself the exception message of the workitem.

      I have described that in section “Variant 2”.

      Another approach could be to populate the technical workflow protocol with the returned messages (you could have a many entries there you need), and then raise the exception. So instead of storing the information into the container, you store it in the protocol instead.

      Please see here, how this is done:

      With the very best wishes,


  3. Karri Kemppi

    Thanks Florin! This is a really helpful and well-written document.

    I was just playing with the CX_BO_TEMPORARY for the first time (normally I have used the CX_BO_ERROR if/when necessary). I never actually thought that the temporary errors will keep the workflow in process status. This is really useful e.g. when someone has locked the object being changed. No need to set the workflow into error status. Just let it try again when RSWWERRE runs again.

    Kind regards,


  4. Mike Pokraka

    Hi Florin,

    Useful blog. One thing I’d like to add is that you don’t need to mess around with OTR, this is all done automatically: When you add text IDs, e.g. SOMETHING_BROKEN, as you noted, a corresponding constant SOMETHING_BROKEN will be created. When you edit the long text, it will create the OTR entries.

    Upon raising the exception, you then just use the constant to specify the text ID, as in:

    raise exception type ZCX_OOPS exporting text_id = ZCX_OOPS=>SOMETHING_BROKEN.



  5. Janosch Kalateh

    Hi all,

    does anyone know if there is such thing like a RESUMEABLE exception for workflows?

    I have a workflow that sends an email in a backgrond step via CL_BCS. After that, there is a dialog step which creates a workitem in the users SWBP.

    When the Email creation fails because of missing Emailaddress in the user master, I want this logged in the WF log, so I am raising an exception.

    Unfortunately, the workflow stops there. I would like it to continue and create a workitem in the users SBWP anyway because the Email is not so critical to the process.



  6. Viveka Schwartz

    Hello Florin,

    thank you very much for this very helpful and excellent blog.

    We have implemented Variant 2 – Using exception with message class. It works fine. However, when the batch job SWWERRE has performed its 3rd attempt, the own message is replaced by WL038 (Work item set to error following 03 failed attempts) in the Work Item Display screen (“Display Message” button and in tab strip Message). (We are on SAPKA74011).

    I can still see the own message in the message list in the technical workflow log (in the popup “Error Diagnosis for work item”) after clicking on the red button of the work item. But for an “application super user”  the technical workflow is very often a bit too technical…

    Perhaps there is already another blog for how to prevent the own message from being replaced in the more user friendly Work Item Display?

    With best regards

    Viveka Schwartz

    1. Florin Wach Post author

      Hello Viveka,

      the messages here are feeding the very detailed technical log, in its first place.

      I wasn’t even aware of, that a workitem, which is not yet completed, can show such a message in the technical-view.

      If that’s the case, the technical-view-button will give you the last error message on that work-item. And if the RSWWERRE failed to execute the batch-item, well, wouldn’t that be interesting to the user, too?

      Meanwhile I’ve found out accidently, how to turn the messages from a red-light into a yellow warning-message style, which is very nice, … and also how to display a piece of the text directly into the log.

      If there’s time, I’ll enhance this post.

      Thx for your feedback, … it’s very appreciated


    2. Florin Wach Post author

      Hello Viveka,

      sorry, I was mixing this up with my blog for the individual entries in the detailed protocol.

      For your requirement I can say: Only the last (error) message will be presented to the user. If the execution failed three times regarding the RSWWERRE, this will be the messages that goes to the user.

      No exceptions.


  7. Saras Jain

    Thanks Florin for this very helpful blog.

    One thing I’d like to add: to throw multiple exceptions in the same method:
    1. You can create 3-4 sub-classes of Class CX_BO_ERROR,

    2. Define your custom Errors under TEXTS tab in these sub-classes:
    Exception ID = DLI_MAINT_ERROR
    Text = Distribution Lists not maintained in ZTWFEXPRBILSO for &INDX1&

    3. Enter them under the Exceptions tab of method:


    4. Finally raising them in the method like:
    WHEN 1.
    RAISE EXCEPTION TYPE zcx_wf_exceptions_with_text1
    textid = zcx_wf_exceptions_with_text1=>dli_read_error
    indx1  = distribution_group.
    WHEN 2.
    RAISE EXCEPTION TYPE zcx_wf_exceptions_with_text2
    textid = zcx_wf_exceptions_with_text2=>dli_nobody_found
    indx1  = distribution_group.
    WHEN 3.
    RAISE EXCEPTION TYPE zcx_wf_exceptions_with_text3
    textid = zcx_wf_exceptions_with_text3=>dli_maint_error
    indx1  = distribution_group.

    You just need to define these classes once and they can be reused across multiple methods and workflows.


Leave a Reply