Jump to content

Aspects of error handling: Difference between revisions

From LabVIEW Wiki
Added content from the FANDOM site. Still in process and adding more detail.
m Add to Error Handling category
 
(19 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{Template:ActiveDiscuss}}
{{TOCnestright}}
Writing VIs and SubVIs that incorporate error handling is considered good form, not only to allow the user indication of abnormal software execution, but also to allow the software to make decisions based on the status of previous operations. Including error clusters in your code assists in troubleshooting, modularity, and user friendliness.
'''Error Handling''' refers to the anticipation, response, and recovery from error conditions.  Writing VIs and subVIs that incorporate error handling is considered good form, not only to allow the user indication of abnormal software execution, but also to allow the software to make decisions based on the status of previous operations. Including error handling in your code assists in troubleshooting ([[debugging]]), modularity, and user friendliness.
LV R&D architect Stephen Loftus-Mercer divides the topic of "error handling" into five (5) separate aspects in order to keep discussions on topic -- error handling is too broad for most conversations. The divisions below were introduced by Stephen Loftus-Mercer in several informal settings; LV R&D architect Darren Nattinger was the first to present them formally.<ref name="dnatterrors"/>


== The Error Cluster ==
{| class="wikitable" style="text-align: left;"
The error cluster is a predefined LabVIEW cluster that is used to contain error status information. The cluster contains the following three components:
|- style="vertical-align:top;"
! Aspect !! Details
|- style="vertical-align:top;"
| '''Error Generation''' is the creation of an [[Error cluster|error cluster]] value at the point that something goes wrong in your LabVIEW code. Feature requests in this area cover readability of the error generation code on the diagram, simplicity of selecting the right error, and packaging valuable metadata with the error (such as the call chain, timestamp, or situation details).<br><br>


{| class="wikitable"
|| Errors may be emitted by both VIs and built-in nodes. When writing a VI that will emit a new error, there are two options:
|-
# (Preferred) Create an error value using one of the library tools, i.e. [[Error Ring]] or ''Error Cluster from Error Code.vi''
! Name
# Directly bundling '''status''' boolean, '''code''' numeric, and '''source''' string together. Doing this will not automatically include the call chain and is very hard to find in code, as you will be searching all Bundle nodes. It is not recommended unless it is done in [[Real Time]], [[FPGA]], or if you are returning an error cluster directly from a non-G DLL.
! Data Type
|- style="vertical-align:top;"
! Description
| '''Error Propagation''' is the act of moving an error value through your LabVIEW code.  When an error has been created it should be propagated or responded to (next section).  Feature requests in this area include ways of aggregating multiple errors together, extending case structure behaviors, stopping loops/systems when errors occur, merging errors from parallel code, hiding error wires and creating some sort of automatic error propagation rules, etc.<br><br>
|-
| Status
| Boolean
| Indicates if an error has occurred (TRUE = error, FALSE = no error).
|-
| Code
| 32-Bit signed integer
| A standardized error code specific to the particular error. LabVIEW has a table of default error codes, although the user is able to define custom error codes. See below for more information.
|-
| Source
| String
| Textual information often describing the error and the VI it occurred within.
|}


== Error Generation ==
|| Propagation is accomplished using the error cluster and wiring from error inputs through the various code paths and out an error outputWhen propagating an error to a subVI, it is considered good practice to place error cluster input and output in the lower quadrants (error in on the left, and error out on the right).  Multiple code/error paths can exist depending on data flow and parallelization.
'''Error Generation''' is the creation of an error value at the point that something goes wrong in your LabVIEW code.  Error can only be generated in two ways:
# Output from a Built-in Node
# G code that creates an error value (i.e. an [[Error Ring]], or using ''Error Cluster from Error Code.vi'')


=== Default Error Codes ===
'''The number one rule of error propagation is ''Don't Break the Error Chain!'''''  An error chain is the code path of the error from the point of generation through the VI hierarchy to the point of being handled by an Error Response, Error Display, and/or Error LoggingA break in the error chain occurs if even one VI in the hierarchy fails to propagate the error correctly. This causes an error from an upstream node to be lost and makes [[Debugging|debugging]] difficult.
The LabVIEW execution system contains a large list of standard and specific errors, encouraging the reuse of generic codes across applications. A list of generic errors codes can be found under the LabVIEW Help menu (figure coming soon...).  Another method of parsing a small number of errors is to select the Help Explain Error menu itemThis will launch an interface that allows the user to enter an error code, and a brief explanation is displayed (figure coming soon...). This interface is also accessible by right-clicking on a front panel error cluster, and selecting Explain Error.


=== Custom Error Codes ===
An error chain can be broken in three ways:
National Instruments has set several error codes aside for custom use. If an existing error code does not adequately describe the error condition, the user can define custom codes that are specific to the application.  Codes between 5000 through to 9999 are available for use, and do not need to conform to any other application. Although General Error Handler.vi can be used to define custom error codes, one can also create an XML file in the labview\user.lib\errors directory that contains custom error codes and their descriptions. This method is particularly useful if the user requires custom error codes to apply to several applications, or if the codes are used by several software engineers in a team or are to be distributed with an application.


For example, the XML filename must be in the format '''*-errors.txt''' (where '''*''' is user definable), and the internal file structure must adhere to the following format:
# Neglecting to wire an output that is part of the error chain
# Zero-iteration [[For Loop|For Loops]]
# Sloppy Merge Errors ordering


<blockquote><br />
To attempt to avoid breaking the error chain, the following [[VI Analyzer]] test can be run:
<?XML Version="1.0"><br />
<nidocument><br />
<nicomment><br />
This is a custom error code definition file for my application.<br />
</nicomment><br />
<nierror code="5000"><br />
User Access Denied!<br />
Contact the Security Department to gain clearance to perform this function.<br />
</nierror><br />
<nierror code="5001"><br />
User Unknown.<br />
Contact the People Development Department.<br />
</nierror><br />
<nierror code="5100"><br />
Driver Unable to Contact Instrument Database.<br />
Contact the Software Engineering Department Helpdesk.<br />
</nierror><br />
<nierror code="5200"><br />
Plug-In Module in R&D mode – not to be used in Production Environment.<br />
Contact the New Product Development Group.<br />
</nierror><br />
</nidocument>
</blockquote>


As can be seen, a file comment can be created within the <nicomment> tag space. Each custom error is defined as an <nierror> with it’s associated error code, and its error message is then placed inside the <nierror> tag space. Although hand coding a custom error code XML file is possible, the Error Code File Editor (Tools->Advanced->Edit Error Codes) provides a simple GUI for file creation and editing (figure coming soon...). Once custom error code files have been created and/or altered, LabVIEW must be
* '''Error Cluster Wired''' - Detects subVIs and functions with unwired error outputs
restarted for the changes to take effectIt is often useful to define code bands during the project planning stage, setting aside bands for specific related error groups.
* '''Unused Code''' - Detects unwired output tunnels of structures
* '''For Loop Error Handling''' - Detects loop-related error propagation and Merge Errors ordering issues on loop error output tunnels (VI Analyzer Toolkit 2018 or later)
|- style="vertical-align:top;"
| '''Error Response''' is what you do in your LabVIEW code when an error occurs and you analyze the error value within the code to respond in a certain way. Feature requests include ways to simplify coding the following behaviors:
* Ignoring certain errors
* Retrying the operation
* Translating or Modifying an error
* Failing the operation and closing the program
<br><br>
||
[[File:Screen Shot 2019-06-27 at 1.50.14 AM.png|600px|thumb]]
See Stephen Loftus-Mercer's poster on [https://forums.ni.com/ni/attachments/ni/3044/3784/2/LabVIEW%20Error%20Responses.pdf Error Responses].
The typical operation of a node is to execute only if no error comes in and may add its own outgoing errorWrapping the entire code of a SubVI within a conditional case structure can make the SubVI act as a typical node (see [[Error Case Structure]]).  However, if the code inside of the structure already operates according to a typical node then the case structure is redundant and keeps the compiler from some optimization it could do if the structure was not there.


----
Also, the developer could choose to enable [[Automatic Error Handling]]. However, automatic error handling assumes all error conditions are tested during development and requires special tooling ([[VI Scripting]]) to enable or disable the entire code base unless every output is wired by the time development is complete.  The experts have strong opinions on whether automatic error handling should be used during development, although all agree that it should never occur in well-written released libraries and applications.<ref name="dnatterrors"/>
'''Note''':
|- style="vertical-align:top;"
This entire section of WIKI about "Error Handling" could benefit from a deep reading of the online help for the General Error Handler.vi. That VI has more facilities than folks typically know. FOR EXAMPLE:
| '''Error Display''' is the act of displaying error information to the end user and/or code developer. Feature requests here include error localization (i.e., generating errors on French system but displaying them on an English system), meaningful translation for error codes, and rendering of the error metadata in a user-friendly form (color, pictures, tables, etc). Display also includes ways of providing advice on common causes of the error and how to fix the error.<br><br>
|| As of LabVIEW 2019, this is almost always accomplished with ''Simple Error Handler.vi'' or ''General Error Handler.vi''.


The General Error Handler.vi includes an input parameter for the type of dialog, one option is "no dialog." I would STRONGLY recommended instead of calling "Error Code Database.vi". The primary reason for the recommendation is that the translation of error code cluster into human readable strings involves much more than just looking up text in the database. The '''source''' string itself may include information to override or extend the database, and the text in either the '''source''' string or the database may include formatting commands, such as HTML tags for bold face. Encoding information in the '''source''' string is a technique that will become more common in the future.  
The ''General Error Handler.vi'' includes an input parameter for the type of dialog, one option is "no dialog." It is recommended to use it instead of calling ''Error Code Database.vi''. The primary reason for the recommendation is that the translation of error code cluster into human readable strings involves much more than just looking up text in the database. The '''source''' string itself may include information to override or extend the database, and the text in either the '''source''' string or the database may include formatting commands, such as HTML tags for bold face. Encoding information in the '''source''' string is a technique that will become more common in the future.  


You may desire to display the text, fully formatted, in a string indicator of your own instead of in any dialog. Use the function of General Error Handler CORE.vi (found on the block diagram of General Error Handler.vi) to do this.
You may desire to display the text, fully formatted, in a string indicator of your own instead of in any dialog. Use the function of ''General Error Handler CORE.vi'' (found on the block diagram of ''General Error Handler.vi'') to do this.
|- style="vertical-align:top;"
| '''Error Logging''' involves taking errors generated by LabVIEW code and logging them to file for later analysis. Error logging is similar to error display (above), but logging has some more interesting variations – recording in a human-readable form or is machine parseable, recording as localized or non-localized. Most importantly, whereas “no error” is not typically displayed to the user, it is critical that we be able to log “no error” so a log file can distinguish a successful run (“no error”) from an aborted/crashed run (one where the log file is empty). Feature requests in this area include mechanisms for making recorded errors readable and assistance debugging errors after the application finishes.  


== Error Propagation ==
|| LabVIEW has no formal error log API because typically logging of errors needs to be folded into the general event logs of an API, which vary radically between applications. The error cluster can be translated into a loggable string by using the ''General Error Handler.vi'', wiring "no dialog" to its input, and writing its string outputs to a log.  
'''Error Propagation''' is the act of moving an error value through your LabVIEW code.


=== Wiring Errors into a SubVI Connector Pane ===
For more insight on why it is important to log "no error", please contemplate [http://thecodelesscode.com/case/48 the 48th koan of Codeless Code]: ''"The Protocols tell us of no fewer than Four Silences: the Silence Before Words, the Silence Between Words, the Silence of the Broken Pipe, and the Silence of Fallen Parcels. To the initiate they are as different as the characters for “end” 末 and “not yet” 未, although the outsider cannot tell one from the other."''
As described above, SubVIs have an associated connector pane, and the placement of error cluster inputs and output is generally in the lower quadrants (error in on the left, and error out on the right), with corresponding exclamation marks over the connectors on the SubVI’s icon (figure coming soon...).
|}
 
 
== Error Response ==
'''Error Response''' is what you do in your LabVIEW code when an error occurs and you analyze the error value within the code to respond in a certain way:
* Ignore certain errors
* Retry an operation
* Translate/Modify an error
* …and many more
See Darren Nattinger's poster on [https://forums.ni.com/ni/attachments/ni/3044/3784/2/LabVIEW%20Error%20Responses.pdf Error Responses].
 
Although one of the simple error responses might be to unbundle the Status Boolean of the error cluster, and feed it to the conditional terminal of a case structure (figure coming soon...), the complete cluster can be wired to it instead (figure coming soon...).  The functionality of the code in (figure coming soon...) and (figure coming soon...) is identical, although its readability is vastly improved as the second example colors the case structure green for the No Error case, and red for the Error case. Wrapping the entire code of a SubVI within a conditional case structure based on the error input allows VIs at higher levels to continue functioning, without executing code that could be useless or even dangerous when an error has occurred.
 
== Error Display ==
'''Error Display''' is the act of displaying error information to the end user and/or code developer. This is almost always accomplished with Simple Error Handler.vi or General Error Handler.vi.
 
== Error Logging ==
'''Error Logging''' involves taking errors generated by LabVIEW code and logging them to file for later analysis.
 
== Example ==
Consider the simple report generation example shown in (figure coming soon...).
 
A report is initially created, a file is then attached, the report is printed, and finally destroyed. The dataflow link between these SubVIs is the report’s reference number (refnum), which ensures each execute in a predefined order. If each of the SubVIs execute without error, then the process completes successfully. Conversely, if one of the SubVIs encounters an error, subsequent SubVIs are unaware of the problem and attempt to execute regardless. In the example above, an error in the Attach a File to the Report SubVI will not cause the Print the Report SubVI to fail, resulting in a blank report print. If effective error handling is introduced (figure coming soon...), the Print the Report SubVI will know if an error has occurred before its execution is requested. If the functional code inside the Print the Report SubVI is enclosed within a conditional case structure based on the error input, the printing code is bypassed, and the error cluster is passed on to the next SubVI.
 
To attain a higher level of user interaction, standard SubVIs exist to alert the user to an error on the error cluster, and prompt for conditional actions. The Simple Error Handler.vi (figure coming soon...) allows for a basic level of error cluster status reporting, displaying detected errors in a dialog box, and prompting the user for an action based on the type of dialog input (for example, OK, Cancel, Stop, etc.).


The Simple Error Handler.vi is a wrapper for the lower level General Error Handler.vi. The latter (figure coming soon...) is more configurable, and permits the dynamic definition of custom error codes, and error exception handling. LabVIEW 7.0 brings with it an addition to the error handling function palette, Clear Errors.vi (figure coming soon...). This VI is simply an error in control and an
error out indicator, which are not linked on the wiring diagram, causing any errors on the wired error link to be cancelled. This VI can be useful when constructing custom error-handling VIs, including dialog boxes allowing user interaction that is not covered by the simple and general error-handling VIs, but should not be used alone. Although dumping the errors from the error cluster may be tempting, one must incorporate appropriate code to handle them.


== External Links  ==
== External Links  ==
*[http://www.ni.com/getting-started/labview-basics/handling-errors Error Handling Basics by NI].
*[http://www.ni.com/getting-started/labview-basics/handling-errors Error Handling Basics by NI].
*[http://bit.ly/dnatterrors What to Expect When You're Expecting an Error by Darren Nattinger]
*[http://controlsoftwaresolutions.com/error-handling-strategies-labview/ David Maidman’s Blog Post].
*[http://controlsoftwaresolutions.com/error-handling-strategies-labview/ David Maidman’s Blog Post].
*[https://forums.ni.com/t5/LabVIEW-Development-Best/quot-SOLID-Error-Handling-quot-presentation-at-NIWeek-2017/td-p/3629639 SOLID Error Handling by Dmitry].
*[https://forums.ni.com/t5/LabVIEW-Development-Best/quot-SOLID-Error-Handling-quot-presentation-at-NIWeek-2017/td-p/3629639 SOLID Error Handling by Dmitry].
*[http://www.ni.com/example/31253/en/ Structured Error Handler Express VI by NI]
*[http://www.ni.com/example/31253/en/ Structured Error Handler Express VI by NI]
*[http://thecodelesscode.com/case/48 The Codeless Code, Koan 48]
== References ==
<references>
<ref name="dnatterrors">Nattinger, Darren. [http://bit.ly/dnatterrors "What to Expect When You're Expecting an Error"] (NIWeek 2018)</ref>
</references>


[[Category:LabVIEW fundamentals]]
[[Category:LabVIEW fundamentals]]
[[Category:Error Handling]]

Latest revision as of 14:53, 17 January 2021

Error Handling refers to the anticipation, response, and recovery from error conditions. Writing VIs and subVIs that incorporate error handling is considered good form, not only to allow the user indication of abnormal software execution, but also to allow the software to make decisions based on the status of previous operations. Including error handling in your code assists in troubleshooting (debugging), modularity, and user friendliness. LV R&D architect Stephen Loftus-Mercer divides the topic of "error handling" into five (5) separate aspects in order to keep discussions on topic -- error handling is too broad for most conversations. The divisions below were introduced by Stephen Loftus-Mercer in several informal settings; LV R&D architect Darren Nattinger was the first to present them formally.[1]

Aspect Details
Error Generation is the creation of an error cluster value at the point that something goes wrong in your LabVIEW code. Feature requests in this area cover readability of the error generation code on the diagram, simplicity of selecting the right error, and packaging valuable metadata with the error (such as the call chain, timestamp, or situation details).

Errors may be emitted by both VIs and built-in nodes. When writing a VI that will emit a new error, there are two options:
  1. (Preferred) Create an error value using one of the library tools, i.e. Error Ring or Error Cluster from Error Code.vi
  2. Directly bundling status boolean, code numeric, and source string together. Doing this will not automatically include the call chain and is very hard to find in code, as you will be searching all Bundle nodes. It is not recommended unless it is done in Real Time, FPGA, or if you are returning an error cluster directly from a non-G DLL.
Error Propagation is the act of moving an error value through your LabVIEW code. When an error has been created it should be propagated or responded to (next section). Feature requests in this area include ways of aggregating multiple errors together, extending case structure behaviors, stopping loops/systems when errors occur, merging errors from parallel code, hiding error wires and creating some sort of automatic error propagation rules, etc.

Propagation is accomplished using the error cluster and wiring from error inputs through the various code paths and out an error output. When propagating an error to a subVI, it is considered good practice to place error cluster input and output in the lower quadrants (error in on the left, and error out on the right). Multiple code/error paths can exist depending on data flow and parallelization.

The number one rule of error propagation is Don't Break the Error Chain! An error chain is the code path of the error from the point of generation through the VI hierarchy to the point of being handled by an Error Response, Error Display, and/or Error Logging. A break in the error chain occurs if even one VI in the hierarchy fails to propagate the error correctly. This causes an error from an upstream node to be lost and makes debugging difficult.

An error chain can be broken in three ways:

  1. Neglecting to wire an output that is part of the error chain
  2. Zero-iteration For Loops
  3. Sloppy Merge Errors ordering

To attempt to avoid breaking the error chain, the following VI Analyzer test can be run:

  • Error Cluster Wired - Detects subVIs and functions with unwired error outputs
  • Unused Code - Detects unwired output tunnels of structures
  • For Loop Error Handling - Detects loop-related error propagation and Merge Errors ordering issues on loop error output tunnels (VI Analyzer Toolkit 2018 or later)
Error Response is what you do in your LabVIEW code when an error occurs and you analyze the error value within the code to respond in a certain way. Feature requests include ways to simplify coding the following behaviors:
  • Ignoring certain errors
  • Retrying the operation
  • Translating or Modifying an error
  • Failing the operation and closing the program



See Stephen Loftus-Mercer's poster on Error Responses. The typical operation of a node is to execute only if no error comes in and may add its own outgoing error. Wrapping the entire code of a SubVI within a conditional case structure can make the SubVI act as a typical node (see Error Case Structure). However, if the code inside of the structure already operates according to a typical node then the case structure is redundant and keeps the compiler from some optimization it could do if the structure was not there.

Also, the developer could choose to enable Automatic Error Handling. However, automatic error handling assumes all error conditions are tested during development and requires special tooling (VI Scripting) to enable or disable the entire code base unless every output is wired by the time development is complete. The experts have strong opinions on whether automatic error handling should be used during development, although all agree that it should never occur in well-written released libraries and applications.[1]

Error Display is the act of displaying error information to the end user and/or code developer. Feature requests here include error localization (i.e., generating errors on French system but displaying them on an English system), meaningful translation for error codes, and rendering of the error metadata in a user-friendly form (color, pictures, tables, etc). Display also includes ways of providing advice on common causes of the error and how to fix the error.

As of LabVIEW 2019, this is almost always accomplished with Simple Error Handler.vi or General Error Handler.vi.

The General Error Handler.vi includes an input parameter for the type of dialog, one option is "no dialog." It is recommended to use it instead of calling Error Code Database.vi. The primary reason for the recommendation is that the translation of error code cluster into human readable strings involves much more than just looking up text in the database. The source string itself may include information to override or extend the database, and the text in either the source string or the database may include formatting commands, such as HTML tags for bold face. Encoding information in the source string is a technique that will become more common in the future.

You may desire to display the text, fully formatted, in a string indicator of your own instead of in any dialog. Use the function of General Error Handler CORE.vi (found on the block diagram of General Error Handler.vi) to do this.

Error Logging involves taking errors generated by LabVIEW code and logging them to file for later analysis. Error logging is similar to error display (above), but logging has some more interesting variations – recording in a human-readable form or is machine parseable, recording as localized or non-localized. Most importantly, whereas “no error” is not typically displayed to the user, it is critical that we be able to log “no error” so a log file can distinguish a successful run (“no error”) from an aborted/crashed run (one where the log file is empty). Feature requests in this area include mechanisms for making recorded errors readable and assistance debugging errors after the application finishes. LabVIEW has no formal error log API because typically logging of errors needs to be folded into the general event logs of an API, which vary radically between applications. The error cluster can be translated into a loggable string by using the General Error Handler.vi, wiring "no dialog" to its input, and writing its string outputs to a log.

For more insight on why it is important to log "no error", please contemplate the 48th koan of Codeless Code: "The Protocols tell us of no fewer than Four Silences: the Silence Before Words, the Silence Between Words, the Silence of the Broken Pipe, and the Silence of Fallen Parcels. To the initiate they are as different as the characters for “end” 末 and “not yet” 未, although the outsider cannot tell one from the other."


External Links


References

  1. 1.0 1.1 Nattinger, Darren. "What to Expect When You're Expecting an Error" (NIWeek 2018)