Access JumpStart 2.0 | Blog

A Rapid Development Framework for Microsoft Access

So this is my latest nested error test code. You can put it in any public code module and run MainProcedure to see what it will do. The thing to do here is to see how Access will behave in various scenarios and the code paths that execute and the ones that don’t.

Sub MainProcedure()
    On Error GoTo MainErrorHandler
    Call NestedProcedure
    'Err.Raise 100, , "Handled Error in MainProcedure"
    Exit Sub
MainErrorHandler:
    MsgBox "Error in MainProcedure: " & Err.Number & " " & Err.Description
    Resume Next
End Sub

Sub NestedProcedure()
    ' Code here will bubble up to the Main Procedure that called it, 
    ' but doesn't return to execute additional code
    'Err.Raise 200, , "Unhandled in NestedProcedure"
    NestedNestedProcedure
    On Error GoTo NestedErrorHandler
    ' Code erroring here will be handled only by the NestedErrorHandler
    'Err.Raise 300, , "Handled in NestedProcedure"
    Exit Sub
NestedErrorHandler:
    MsgBox "Error in NestedProcedure: " & Err.Number & " " & Err.Description
    Resume Next
End Sub

Sub NestedNestedProcedure()
    'Err.Raise 400, , "Unhandled in NestedProcedure"
    On Error GoTo NestedNestedErrorHandler
    ' Code erroring here will be handled only by the NestedErrorHandler
    'Err.Raise 500, , "Handled in NestedProcedure"
    Exit Sub
NestedNestedErrorHandler:
    MsgBox "Error in NestedNestedProcedure: " & Err.Number & " " & Err.Description
    Resume Next
End Sub

MainProcedure calls NestedProcedure, NestedProcedure calls NestedNestedProcedure, so 3 levels of code can be traversed through.

Initially I have all Err.Raise statements commented out and this will do absolutely nothing.

Uncommenting Err.Raise 500 results in this message box:

The third level subroutine has this routine in an error handler. It gets handled there and nowhere else.

Uncommenting Err.Raise 500 and Err.Raise 400 results in this message box:

The error is unhandled in the third level and is unhandled in the second level, so is handled in the first level handler. Resume Next does not return to the third level function, it resumes the next line in the top level function.

Uncommenting Err.Raise 500 and Err.Raise 400 and Err.Raise 100 results in these message boxes:

So again, we never run the Err.Raise 500 code because it was short circuited by the Err.Raise 400, but we also see Err.Raise 100 because code execution continued in the MainProcedure.

Uncommenting Err.Raise 500 and Err.Raise 100 results in these message boxes:

Now 500 was handled inside the NestedNested handler, and 100 in the MainProcedure handler.

I think this shows the general gist of the experiment.

Raised errors are handled inside the first error handler defined moving back up the execution stack. Resuming in the error handler will resume in the procedure which handled the error and never return to execute any more code in the lower level.

If you need an error to be handled and then bubble up, you will want to set a flag, then resume next in the procedure, then use On Error Goto 0 as the next line, then do another Err.Raise. That will allow you to pass a new error up to the parent function (which you can mimic to be the same number and description as the original error).