Skip to main content

Thrown Fault with Catchall

Thrown Fault with Catchall

When a <throw> statement executes, its fault value is an expression that evaluates to a string. Faults are not objects, as in other object-oriented languages such as Java; they are string values. When you specify a fault string it needs the extra set of quotes to contain it, as shown below:

<throw fault='"thrown"'/>

When a <throw> statement executes, control immediately goes to the <faulthandlers> block inside the same <scope>, skipping all intervening statements after the <throw>. Inside the <faulthandlers> block, the program attempts to find a <catch> block whose value attribute matches the fault string expression in the <throw> statement. This comparison is case-sensitive.

If there is a <catch> block that matches the fault, the program executes the code within this <catch> block and then exits the <scope>. The program resumes execution at the next statement following the closing </scope> element.

If a fault is thrown, and the corresponding <faulthandlers> block contains no <catch> block that matches the fault string, control goes from the <throw> statement to the <catchall> block inside <faulthandlers>. After executing the contents of the <catchall> block, the program exits the <scope>. The program resumes execution at the next statement following the closing </scope> element. It is good programming practice to ensure that there is always a <catchall> block inside every <faulthandlers> block, to ensure that the program catches any unanticipated errors.

Suppose you have the following BPL. For reasons of space, the <start> and <end> elements are not shown.

BPL diagram with several shapes surrounded by a rectangle with a dashed line in the middle

This BPL business process does the following:

  1. The first <trace> element generates the message before scope.

  2. The <scope> element starts the scope.

  3. The second <trace> element generates the message before assign.

  4. The <throw> element throws a specific, named fault ("MyFault").

  5. Control now goes to the <faulthandlers> defined within the <scope>. The <scope> rectangle includes a horizontal dashed line across the middle; the area below this dashed line displays the contents of the <faulthandlers> element. In this case, there is no <catch> but there is a <catchall> element, so control goes there.

    Note that InterSystems IRIS skips the third <trace> element.

    If we drill down into <catchall>, we see this:

    BPL diagram with the following elements in order: start, trace, trace, trace, end

  6. Within <catchall>, the first <trace> element generates the message in catchall faulthandler.

  7. Within <catchall>, the second <trace> element generates the message that provides information on the fault using $System.Status methods and the special variables %Context and %LastError. The %LastError value as the result of a thrown fault is different from its value as the result of a system error:

    • GetErrorCodes returns <Ens>ErrBPLThrownFault

    • GetOneStatusText returns text derived from the fault expression in the <throw> statement

  8. Within <catchall>, the third <trace> element generates a message that provides information on the fault using the BPL context variable %LastFault. It contains the text derived from the fault expression from the <throw> statement.

  9. The <scope> ends.

  10. The last <trace> element generates the message after scope.

Event Log Entries

The corresponding Event Log entries look like this:

Error message stacked above in catchall faulthandler

XData for This BPL

This BPL is defined by the following XData block:

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before scope"'/>
    <scope>
      <trace value='"before assign"'/>
      <throw fault='"MyFault"'/>
      <trace value='"after assign"'/>
      <faulthandlers>
        <catchall>
          <trace value='"in catchall faulthandler"'/>
          <trace value=
            '"%LastError "_
            $System.Status.GetErrorCodes(..%Context.%LastError)_
            " : "_
            $System.Status.GetOneStatusText(..%Context.%LastError)'
            />
          <trace value='"%LastFault "_..%Context.%LastFault'/>
        </catchall>
      </faulthandlers>
    </scope>
    <trace value='"after scope"'/>
  </sequence>
</process>
}
FeedbackOpens in a new tab