Error handling strategies in LabVIEW
David Maidman – Control Software Solutions
Introduction
Error handling is an essential part of a professional LabVIEW application, however is something that is often overlooked. Without adequate error handling applications can be hard to debug, provide a bad user experience and in the worst case can cause damage to equipment, loss of data and even injury.
When starting out with LabVIEW one of the first things we are taught is the importance of error handling. In these early days the general advice is that we should always enclose block diagram code in an error case and that we should always wire errors between our subVIs. However, in practice this advice does not always provide an adequate error handling strategy when creating professional applications, and in some circumstances causes more problems than it solves.
Local Error Handling
Often when an error occurs, rather than passing it downstream it can be dealt with there and then. How you handle the error depends on the specific error and the software requirements. Often when an error occurs we might decide to handle it locally by one of three ways; ignore it, modify it, or retry.
Ignore
Sometimes it is possible to simply ignore an upstream error. One common example might be a communications timeout error when reading from a TCP connection. In the case of a timeout the read VI returns an error because it failed to successfully carry out its primary job, however in the context of your application this might not be seen as an error and therefore it can be cleared (for example it could be that there are no messages to read).
Figure 1 clearing a timeout error
Figure 2 example of how a specific error can be cleared
Modify
Some errors may provide information that can be used downstream, even if you do not consider them to be errors. In this case you could choose to downgrade an error to a warning. In this case the error cluster retains the useful information, however does not prevent downstream code from executing. One example would be when creating a new directory: if the directory already exists an error will be generated, however if the reason you are creating the directory is simply to ensure that it exists then you might not want an error to be generated.
Figure 3 downgrading an error to a warning
Another reason you might want to modify an error is to change the error code to one specific to your application.
Figure 4 changing a default error code to one specific for the application
Retry
Sometimes you might only be interested in an error if it occurs a number of times. An example might be when attempting to initialise a DAQ device when the device has not been connected. In this example you might clear the error and then retry.
Figure 5 implementing a ‘retry on error’ strategy
Asynchronous Error Handling
You might not always want to handle errors locally and therefore it might be necessary to pass error information to another module to be handled. In this case you can use queued message handlers if you have a dedicated error handling module, or by user events if you want modules (for example a state controller or user interface) to subscribe to error messages.
Figure 6 adding errors to a queue to handle in another loop
Figure 7 publishing errors as events to be handled by subscribing processes
In practice you are likely to use a combination of local and central error handling depending on the requirements of your project.
Error Handling Guidelines
- Before enclosing the block diagram of a VI in an error case consider as yourself the question ‘should the code in this VI run if there is an upstream error?’ Only if the answer is ‘No’ should you enclose the code in an error case.
- In general shutdown code should always execute, therefore do not enclose the code within an error case, rather merge the input error with the error stream at the output of the subVI.
- Remember to maintain separate error streams for unrelated functions.
- If possible handle errors where they occur.
- Consider what you what you want to happen in the event of an error (ignore, retry, modify).
- Errors can provide useful information – downgrade to warnings if you want to maintain the error information without triggering an error.
- Handle errors gracefully and always avoid crashing the application when an error occurs.
- Log unhandled errors to allow useful debug information.
- Always consider error handling in the requirements and detailed design phase of your project.
Figure 8 do not enclose shutdown code in an error case
Figure 9 merging incoming errors with the output error stream to ensure the shutdown code executes
Further Information
For more information on any of the topics you have read in this article, or for more information on LabVIEW programming contact us:
Just one question: In Figure 1, I understand that the TCP Read node is the one that enters in error condition due to time out. In that case, the error output wire from the TCP Read node would have the status set to true, then the case structure (the larger one) would go to the Error case. Is this correct?
If so, shouldn’t this structure be in the Error case, in red?