Error handling just got even easier

Introduction

We have been discussing the use of transactions since Todd Geist’s post in 2014. We introduced a complete framework with the Karbon project in 2018. We then revisited this framework with the introduction of the new script steps introduced in version 19.6. Transactions have proven to be useful for handling errors and creating/editing/deleting multiple records at the same time. In version 21.0 there is now support for Revert Transaction in subscripts. Before this release, the Revert Transaction step was ignored in subscripts when a controlling script already had an open transaction. What does this new behavior mean? 

What’s New

If a revert condition is met in a subscript, the entire transaction chain (including the controlling script) is reverted. 

Problem Statement

In versions 19.6 through 20.x, native FileMaker transactions had some limitations. Before this feature was available, when a transactional script called another transactional script – the following script steps would yield an Error 3 (Command Unavailable) in the subscript: Open Transaction, Revert Transaction, and Commit Transaction. If the Revert condition was met in the subscript, the Revert would not propagate up to the calling script as one might expect. Regardless of whether your transactional script was going to be called by a non-transactional or a transactional script, you would have to trap every error twice. 

Below is a short example of the double error guarding that used to be necessary in a transactional subscript. 

Implications

1. Ignoring error 3

Open Transaction and Commit Transaction in a subscript still yield an Error 3. Do not fret about Error 3s, though. We shared our transactional scripting pattern in a previous post.  Our scripting pattern will continue to ignore the Error 3s that are thrown after Open Transaction and Commit Transaction because these are not fatal errors. The good news is that Revert Transaction will no longer yield an Error 3 in a subscript

2. Error guarding

Guarding against errors goes hand-in-hand with transactions. In version 21.0 we can use Revert Transaction to handle errors whether or not the error is found in a subscript. This greatly improves and simplifies error handling. Where we previously had to manage errors twice in subscripts, the revised Revert Transaction functionality would work if called if the Revert condition is met in a subscript.

3. Passing errors back up the call stack using standard error codes

Let’s say we have two transactional scripts: Create Customer { json } and Create Address { json }. Now, suppose want to create an address at the same time I create a customer.  Within the Create Customer script, which controls the transaction, we  call the Create Address transactional subscript at line 83. Let’s discuss what happens when the subscript encounters an error. 

Create Address requires a JSON parameter. I’m going to force an error by passing an empty parameter to see the result. 

Controlling transactional script – Create Customer { json }

Transactional subscript – Create Address { json }

Note that within the Revert Transaction step, we are setting the error message to an object using the error.Set() custom function (line 61). 

When you use the custom function above and the custom error code 5499, the Revert Transaction step will return the error object up to the calling transaction script. 

Here is what the error object looks like when it’s read into the calling script: 

What if you don’t use an object as the error message? You can set the error message to a descriptive string instead of a JSON object and use a different custom error code (in the range 5000-5499). 

Here is an example of the error.GetLast() result in the calling script:

The main difference between these two methods is the error code. Although we used code 5499 in the Revert step, the code that we see in the first error example is 960. When we look up 960 in the Claris docs https://help.claris.com/en/pro-help/content/error-codes.html, we see that it represents an invalid parameter error. At Proof+Geist, we like to use FileMaker’s existing error codes when appropriate because they have a standard definition that any developer could look up. While FileMaker allows developers to use custom error codes 5000-5499 in the Revert Transaction step introduces the burden of maintaining documentation for these custom error codes. In the example above, it is unclear what 5102 means, whereas 960 is already defined by FileMaker and can be easily looked up.

Considerations

What happens if we’re three or four scripts deep and we call Revert Transaction? In the call stack below, you’ll notice a controlling transactional script that calls subscript 1, which calls subscript 2, and so on. In subscript 3, an error is thrown by attempting to set a calculation field. This error causes the process to jump ahead to the Commit Transaction step of Subscript 3. This then jumps to the Commit Transaction step of Subscript 2, and so on, until I reach the Commit Transaction step of the controlling script, where the error is actually processed. 

You can observe the error being passed up in the script debugger below. 

Here is the final error result: 

Conclusion

With the revised Revert Transaction script step, we gain modularity in transactional scripting and simpler error handling in subscripts. By using error objects as the Error Message attribute, we can accurately pinpoint and describe the location and nature of errors in a transactional subscript. We believe this is the most effective method for returning detailed error information. We encourage you to continue utilizing the scripting pattern we’ve developed, now enhanced and fully supported in subscripts.

Check out FileMaker 2024 here, and sign up for the trial.