Visible Progress Home We make progress visible.
Search Site:
Resources > VB6 Coding Tips  
VB Quality Zone
VB6 Coding Tips
Self-documenting Code
Coding Standards
Naming Conventions
Error Handling
Binary Compatibility
Performance Tuning
Source Metrics
Process Tips
Testing Tips

Our Customers...
What Customers Say...

VS Law 2005 - VB.NET 2005 coding standards enforcement.
Try our products for free today.
VS Law .NET - VB.NET 2002/2003 coding standards enforcement.
Try our products for free today. VB Law - VB6 coding standards enforcement.
 
  VB Law - Quality assurance for Visual Basic source code.  
 

Visual Basic Error Handling

Expect Errors! Make Your VB Error Handling Exceptional

Run-time errors are an expensive fact of life both during development and following the release of software to customers. Errors take time to find and time to fix. Users soon become frustrated when software fails to function as expected without adequate warning or explanation putting your reputation at stake. It is therefore extremely important that you consider carefully how your application will handle and report errors. Designing and implementing an effective error handling strategy can accelerate development and significantly reduce development and support costs whilst maintaining (or even enhancing) your reputation.

Unless you take deliberate steps in your code to trap and handle errors, Visual Basic (VB) will 'handle' them for you. It does so by displaying a simple message box prior to abruptly terminating your application without any 'QueryUnload', 'Unload' or 'Terminate' events!

To prevent your application users being unceremoniously dumped by VB's default error handling behaviour, it is essential that all errors are correctly handled by your application. However, there is more to effective error handling than just placing an error trap in every procedure and displaying the property values of the VB 'Err' object whenever an error occurs.

Adopt A VB Error Handling Strategy

Enforce your VB error handling strategy effectively with VB Law.
VB Law
Quickly detect and correct code that violates your VB error handling strategy.
Implementing an effective VB error handling strategy ensures the following:
  • Errors do not go undetected.
  • Applications do not terminate abruptly without warning or explanation.
  • Components are robust and predictable.
  • After an error, application stability is restored.
  • Error messages offer the user a meaningful description of an error.
  • Error messages advise the user of the possible impact of an error.
  • Error messages offer the user advice that may remedy a problem and avoid unnecessary support calls.
  • Error messages advise the user on how to proceed.
  • Error messages offer sufficient information for support personnel to quickly identify known problems.
  • Legitimate run-time errors are not confused with software defects.
  • Errors are logged to avoid incorrect reporting by users during support calls.
  • Error logs can be viewed and cleared easily.
  • The source code location of an error can quickly be determined.
  • The cause of an error can be determined more easily allowing defects to be corrected more easily.
  • The user/system is not swamped by repeated error reporting.
  • Note: For your VB error handling strategy to be successful, it should be implemented from the outset of a project. Developers must also understand the business reasons why error handling is important and necessary in addition to being thoroughly conversant with VB's error handling behaviour and functionality.

    Understand Visual Basic Error Handling

    Errors Are Handled By The 'Active' Error Handler

    At run-time there is always one active error handler. Unless your application registers an error handler of its own (using an 'On Error' statement), the active error handler will be VB's own default handler!

    VB error handlers can become nested as calls become nested on the call stack. The active error handler is always the most recently registered handler and any error occurring will be trapped by that handler.

    Errors occur within the currently executing procedure when either an error is raised (using 'Err.Raise') or when a statement fails generating an error.

    If a procedure does not register its own error handler then any error occurring directly within that procedure will pass back up the call stack to the procedure owning the currently active error handler and will be trapped by that procedure instead. A consequence of this is that the procedure in which the error occurred has no opportunity to clean up before control is handed to the active error handler.

    If the current procedure has an active error handler when an error occurs, code execution moves to the statement designated by the active error handler and an opportunity exists to clean up before exiting.

    VB Error Handlers Must Be Registered

    Enforce your VB error handling strategy effectively with VB Law.
    VB Law
    Quickly detect and correct procedures with missing error handlers.
    There are three ways of registering an error handler:
  • On Error GoTo <label>
  • On Error Resume Next
  • On Error GoTo 0
  • Using the 'On Error GoTo <label>' statement directs execution to re-start at the specified <label> in the event of an error. Error handling code is normally placed at the end of a procedure to aid source code readability. If so, you must ensure that execution does not accidentally 'fall through' into your error handler code.

    Using the 'On Error Resume Next' statement directs execution to re-start at the statement after the statement which 'generated' the error. If the error occurred in a nested procedure with no active error handler then the 'next' statement will actually be that of the active error handler and not the statement following the statement which generated the error.

    The 'On Error GoTo 0' statement removes any active error handler for the current procedure thereby directing errors back up the call stack to the last registered error handler (now the active error handler).

    Error Numbers Are Not Unique

    Error numbers need to be predictable if they are to be trapped and handled intentionally. Unfortunately, there is nothing to prevent different components from generating the same error number. Your error handling strategy must acknowledge this as must your application design.

    Tips For Improved VB Error Handling

    Indicates ways in which VB Law can automatically enforce your VB error handling strategy.

    Ensure All Procedures Contain An Error Handler

    Enforce your VB error handling strategy effectively with VB Law.
    VB Law
    Quickly detect and correct procedures with overly complex error handling.

    Unfortunately, to avoid VB's default error handling behaviour, it is necessary to code error traps and handle errors directly within your application. Although sounding somewhat drastic, adopting the rule that all procedures must contain an error handler will ensure that all errors are intercepted before VB's default error handling behaviour gets a look in. This approach also leaves little room for misunderstanding by developers when coding. (If you log errors, this approach leads to a log trace showing the exact origin of each error which is helpful during debugging and customer support.)

    Define A Convention For Label Names

    VB's usage of 'GoTo' (Doh!) as part of its error handling mechanism, means it's also a good idea to have rules for label names within procedures. Many VB developers favour use of the procedure name with '_Error' or '_Exit' appended as appropriate but the choice of convention is yours.

    Use A Single Error Trap Per Procedure

    Adopting the rule of a single error trap per procedure generally keeps both error handling and application logic simple and readable. Always end the error handler with a 'Resume', 'Resume Next', 'Resume <label>', 'Exit Sub/Function/Property', 'End Sub/Function/Property' or 'Err.Raise' statement.

    Raise Unexpected Errors On

    Code failing unexpectedly can leave your application in an unstable state. To recover, you must ensure that each procedure within your application is capable of handling unexpected errors and performing the necessary clean up work to restore stability.

    By raising unexpected errors on, errors cascade upwards through the call stack of nested calls allowing each procedure in turn to clean up and free claimed resources. This approach will also eventually allow a top-level procedure to report the error to the user. (If you log errors, this leads to a log trace showing the origin of the error and also each procedure on the call stack at the time of the error.)

    Note: Raising errors in top-level procedures of standalone applications or within Class_Terminate events will hand control back to VB's default error handler and should therefore be avoided.

    Isolate And Handle Expected Errors

    Enforce your VB error handling strategy effectively with VB Law.
    VB Law
    Quickly detect and correct procedures with code that falls through into the error handler code.

    Many of Visual Basic's intrinsic commands raise errors to signal failure. On such occasions you may wish your application to take advantage of this behaviour and be more responsive to the circumstances at hand. To achieve this your application must anticipate particular errors and handle them accordingly.

    By isolating statements which you expect to raise errors into separate procedures you can avoid ambiguity as to which statement caused the error and how particular error numbers for that statement are handled. This approach also ensures that the same error number occurring under different circumstances is correctly interpreted and handled on each occasion.

    Avoid Use Of 'On Error Resume Next'

    Many VB developers use the 'On Error Resume Next' statement as a poor replacement for the C++ 'Try...Catch' style of exception handling. However, this approach generally leads to longer procedures and is best avoided in preference to isolation of statements expected to generate errors (as described above).

    Avoid Use Of 'On Error GoTo 0'

    Rarely should the need arise to disable the current procedure's active error handler in favour of a calling procedure's error handler (or VB's default error handler) and therefore the 'On Error GoTo 0' should be avoided. Use of this statement also infers that a procedure has an intimate knowledge of its caller which might become a dangerous assumption if the procedure is later re-used by other procedures.

    Avoid Using Return Codes To Communicate Success Or Failure

    Use return codes to return information and raise errors to indicate unexpected failure.

    A major criticism of return codes is that they all too often get ignored causing errors to propagate to higher levels of an application making errors more difficult to detect and correct. Alternatively, when return codes are tested, the code for procedures can soon become bloated by excess nesting of condition statements testing return codes for success.

    Other reasons for avoiding use of return codes include:
  • The differing values assigned to return codes for success and failure can be a source of bugs.
  • Use of return codes mandates the use of 'Functions' everywhere as 'Subs' do not support propagation of return codes without use of ByRef parameters.
  • Return codes offer little information about an error when compared to the 'Err' object.

  • 'Garbage In' Is No Excuse For 'Garbage Out'

    Errors often occur when incorrectly initialised variables are inadvertently passed as parameters to procedures which have specific entry requirements. If such a procedure fails to validate its parameters on entry then an unexpected run-time error may well occur or worse still, unexpected behaviour is exhibited far away from the 'scene of the crime'.

    The 'Debug.Assert' statement offers assistance during debugging and unit testing within the VB integrated development environment (IDE) as a useful method of verifying that parameter entry values and other designated expressions fall within expected limits, otherwise execution is halted at the 'Debug.Assert' statement. Unfortunately, the scope of this command is limited to run-time testing within the IDE and, unless your application is thoroughly unit tested in the IDE, offers no benefit to the compiled application.

    Note: If you intend to achieve a high level of re-use and robustness for your code, the time invested in coding argument assertions to verify and log erroneous entry values is well worth the effort as errors are identified much closer to the source of the problem. This is especially true if you choose to code your own version of the 'Debug.Assert' statement that is effective in compiled applications too.

    Raising Your Own Errors

    From time to time your application may need to raise errors of its own to communicate unexpected failure to a calling procedure. When raising an error, it is important that you consider the argument values carefully that will be used as the parameters to the 'Err.Raise' method. Failing to supply sufficient or appropriate information can hamper support as well as debugging.

    Arguments For Err.Raise
    Number A long integer containing the error number. Because error numbers cannot be guaranteed to be unique, you have some latitude here to experiment with values and their meaning. Always document your chosen error numbers and the circumstances under which they arise.
    [Source] Optional. A string containing information regarding the source of the error. This should contain as much information as possible to pin-point the exact location of the error e.g. component filename, component version, source filename and procedure name.
    [Description] Optional. A string containing information describing the error. If unspecified, the value in Number is examined. If it can be mapped to a Visual Basic run-time error code, the string that would be returned by the Error function is used as Description. If there is no Visual Basic error corresponding to Number, the message "Application-defined or object-defined error" is used.
    [HelpFile] Optional. A string containing the full filename of the help file which can provide information about the error. If unspecified, Visual Basic uses the fully qualified drive, path, and file name of the Visual Basic Help file.
    [HelpContext] Optional. A string containing the help context ID of the topic associated with the error. If omitted, the Visual Basic Help file context ID for the error corresponding to the Number property is used, if it exists.

    Test Your Error Handling!

    While you may anticipate your error handling code may only execute under rare circumstances, it too has to be tested like all other code. To see how your error messages will be received and/or logged, try raising some fictional errors during unit testing.

    Note: If your application is to be deployed by overseas customers in a different time zone and who speak a different language, the extra effort invested testing and correcting your application's error handling might help prevent accelerated user frustration (as well as preserve your normal sleeping pattern!).

    Tips For Improved Error Reporting

    There is nothing worse than an error that your application knows about but that you don't! Many developers have experienced a positive acknowledgement on screen but later noticed that the error log has grown. The natural impulse is to examine the log, fix the errors and forget to improve the application's on screen error reporting. However, it is important that errors are not neglected but rather that they are correctly reported to the right audiences.

    Inform The Correct People In A Helpful Way

    When reporting errors to the end user via a graphical user interface, avoid cryptic messages. Instead ensure that error messages are informative i.e. explain the likely impact of the problem and how to proceed. Do not rely on the user to write anything down or remember the error message or what they were doing at the time.

    In the case of those diagnosing a problem, it is necessary to know more about the circumstances and components involved at the time of the error. An error log can be used to record such vital information at the time of the error and may later be used by support personnel (to identify known problems for which a solution or workaround already exists) or developers to identify and correct defects.

    Don't Get Over Enthusiastic

    Error reporting must be suitably placed within code such that unnecessary repetition of error notifications is avoided. Too many errors reported continuously may cause the user to terminate your application abnormally. Also consider carefully how often, and under what circumstances, your application will write to the system event log and the actions you expect system administrators to take in response to such events.

    Log All Errors

    Errors aren't usually planned so it's best to be prepared for them when they happen. You can never have too much information about an error, so log as much information as possible. Applications/components which run on a server and do not have a graphical user interface rely heavily on logging to communicate errors.

    The method of error logging adopted may vary from logging to a file, database or the system event log depending on the nature of your application or components. Regardless of the logging mechanism employed, it is helpful to provide easy access to view the log and also to clear the log when necessary.

    Note: If your application is distributed across multiple computers, it's best to log errors to a central location.

    Error Log Entries

    Each error log entry should contain the following information:
  • Entry type (warning, error, debug trace etc.).
  • Date and time of the error.
  • Physical machine name.
  • Process ID.
  • Thread ID.
  • Application/component name.
  • Application/component version.
  • Error number.
  • Error source (including source file and procedure name).
  • Error description.
  • Procedure arguments.
  • ObjectContext information (transaction/security details).
  • Create An Error Log Viewer

    Providing an application to analyse your error logs can be extremely helpful to those attempting to diagnose problems and test applications. During development, error logs usually become cluttered with debug trace information so providing a facility to filter log entries on certain criteria can be a great help. The same application might also ship as part of your end product as a diagnostic support tool.

    Enforce Your Error Handling Strategy

    VB Law - VB6 coding standards enforcement.

    Having an error handling strategy is one thing, implementing it successfully is another. To ensure your strategy is implemented correctly you may wish to extend your VB coding standards to include rules applicable to your error handling strategy and to include error handling as a topic to be covered during application design and peer code reviews.

    VB Law can quickly and effectively help enforce VB coding standards for error handling. Visit our downloads page and trial VB Law for free today.