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 Nextinstructs VBA to suppress runtime error popups and immediately execute the line of code directly following the failed statement.On Error GoTo 0disables 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:
| Directive | Impact on Runtime Engine | Impact on Err Object | Typical Use Case |
|---|---|---|---|
On Error Resume Next | Suppresses halts; steps to next line. | Populates Err.Number silently. | Localized tests for missing items. |
On Error GoTo 0 | Re-enables default modal crash prompts. | Resets and clears the Err object. | Closing a localized suppression block. |
On Error GoTo -1 | Clears the active exception state. | Resets internal exception flags. | Transitioning between multiple error handlers. |
On Error GoTo Label | Jumps 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.