Using On Error Resume Next vs. On Error GoTo 0 (The right way).

In Excel VBA, unhandled errors immediately halt execution and display cryptic runtime dialog boxes to users. To manage expected faults, developers turn to error directives. However, misusing On Error Resume Next is one of the most common anti-patterns in automation, often masking fatal bugs, creating corrupt data, and leaving applications in unstable states.

What Is the Difference Between On Error Resume Next and On Error GoTo 0?

On Error Resume Next instructs VBA to suppress runtime error popups and immediately execute the line of code directly following the failed statement. On Error GoTo 0 disables this error suppression, resetting the runtime error handler so that any subsequent failures halt execution and trigger the standard VBA error dialog.

The “Surgical” Pattern (The Right Way)

On Error Resume Next should never be left active across an entire procedure. Instead, treat it like a surgical scalp: enable it immediately before a single line that might throw an expected non-fatal error, check the result, and immediately deactivate it using On Error GoTo 0.

Sub SafelyAccessSheet()
    Dim ws As Worksheet

    ' 1. Enable suppression ONLY for the risky line
    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets("MonthlyReport")

    ' 2. Immediately disable suppression
    On Error GoTo 0

    ' 3. Evaluate whether the operation succeeded
    If ws Is Nothing Then
        MsgBox "The 'MonthlyReport' sheet does not exist.", vbExclamation
        Exit Sub
    End If

    ' Normal execution resumes with full error protection active
    ws.Range("A1").Value = "Audit Complete"
End Sub

If On Error GoTo 0 had been omitted, any typo or logic failure in the rest of the procedure—such as an invalid formula or a range boundary error—would fail silently without warning.


The Danger of Blanket Error Suppression

When you place On Error Resume Next at the top of a subroutine without resetting it, VBA ignores every catastrophic failure that follows.

Consider this real-world trap:

Sub DangerousDataPurge()
    On Error Resume Next ' Applied globally

    Dim ws As Worksheet
    Set ws = Worksheets("ArchiveData") ' Typo: actual tab is "Archive_Data"

    ' Because ws is Nothing, this line fails silently
    ' BUT execution continues to the next line!
    ws.Cells.ClearContents

    ' If the developer fell back on ActiveSheet references later:
    ActiveSheet.Cells.ClearContents ' Wipes whatever sheet the user was viewing!
End Sub

Because error suppression was broad, the code failed to assign the worksheet object, silently threw Runtime Error 91: Object variable or With block variable not set (The Set keyword trap)., skipped the intended clear operation, and continued executing downstream destruction.


When to Use On Error Resume Next

There are specific, legitimate administrative scenarios where a method has no native “test-before-execute” function and will throw an error under normal conditions:

1. Testing for Object Existence

Testing whether a collection contains a specific key, sheet, or dictionary entry:

Function FileIsOpen(wbName As String) As Boolean
    Dim wb As Workbook
    On Error Resume Next
    Set wb = Workbooks(wbName)
    On Error GoTo 0
    FileIsOpen = Not wb Is Nothing
End Function

2. Deleting Objects That Might Not Exist

Attempting to delete a temporary shape, filter, or worksheet without querying the entire parent collection:

On Error Resume Next
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("Temp_Cache").Delete
Application.DisplayAlerts = True
On Error GoTo 0

3. Reading Registry Keys or Environment Variables

Querying optional system variables where a missing key returns an error rather than an empty string:

Dim userSetting As String
On Error Resume Next
userSetting = CreateObject("WScript.Shell").RegRead("HKCU\Software\MyApp\Settings\Path")
On Error GoTo 0

Clearing the Err Object Explicitly

When wrapping risky code, always clear the Err object using Err.Clear if you plan to inspect Err.Number across multiple consecutive tests:

On Error Resume Next
Err.Clear
Set targetRange = Range("CustomDataRange")

If Err.Number <> 0 Then
    Debug.Print "Named range not found. System error: " & Err.Description
    Err.Clear
End If
On Error GoTo 0

Using silent logging tools like Debug.Print: The developer’s best friend for silent error logging. ensures you retain full visibility during development without exposing raw runtime prompts to end users.


Diagnostic Comparison: Error Directive Behaviors

Understanding what each error instruction does to the internal VBA state engine is essential for clean architecture:

DirectiveImpact on Runtime EngineImpact on Err ObjectTypical Use Case
On Error Resume NextSuppresses halts; steps to next line.Populates Err.Number silently.Localized tests for missing items.
On Error GoTo 0Re-enables default modal crash prompts.Resets and clears the Err object.Closing a localized suppression block.
On Error GoTo -1Clears the active exception state.Resets internal exception flags.Transitioning between multiple error handlers.
On Error GoTo LabelJumps execution to a named label.Preserves error details for handling.Structured procedure-level error handling.

When your goal is not simply bypassing a known missing item but managing unexpected system crashes across an entire application, you need structured branching rather than line suppression. Learn how to architect full recovery routines in Building a Global Error Handler: The Err.Number and Err.Description guide..

If an unexpected crash leaves your screen frozen or calculations locked, you can restore system defaults using Building a “Reset” macro to fix Excel settings after a crash (Calculation, ScreenUpdating).. For a complete overview of professional debugging frameworks, consult the VBA Debugging Masterclass: Professional Techniques to Audit and Clean Your Code.